91th Cygnus<->FSF quick merge
[platform/upstream/gcc.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 "tree.h"
25 #include "cp-tree.h"
26 #include "flags.h"
27 #include "output.h"
28 #include "assert.h"
29
30 #ifndef INT_TYPE_SIZE
31 #define INT_TYPE_SIZE BITS_PER_WORD
32 #endif
33
34 extern tree define_function ();
35 extern tree build_t_desc_overload ();
36 extern struct obstack *permanent_obstack;
37
38 tree type_info_type_node;
39 tree tinfo_fn_id;
40 tree tinfo_fn_type;
41 \f
42 void
43 init_rtti_processing ()
44 {
45   type_info_type_node = xref_tag
46     (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
47   tinfo_fn_id = get_identifier ("__tf");
48   tinfo_fn_type = build_function_type
49     (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
50      void_list_node);
51 }
52
53 /* Given a pointer to an object with at least one virtual table
54    pointer somewhere, return a pointer to a possible sub-object that
55    has a virtual table pointer in it that is the vtable parent for
56    that sub-object.  */
57
58 static tree
59 build_headof_sub (exp)
60      tree exp;
61 {
62   tree type = TREE_TYPE (TREE_TYPE (exp));
63   tree basetype = CLASSTYPE_RTTI (type);
64   tree binfo = get_binfo (basetype, type, 0);
65
66   exp = convert_pointer_to_real (binfo, exp);
67   return exp;
68 }
69
70 /* Given the expression EXP of type `class *', return the head of the
71    object pointed to by EXP with type cv void*, if the class has any
72    virtual functions (TYPE_VIRTUAL_P), else just return the
73    expression.  */
74
75 static tree
76 build_headof (exp)
77      tree exp;
78 {
79   tree type = TREE_TYPE (exp);
80   tree aref;
81   tree offset;
82
83   if (TREE_CODE (type) != POINTER_TYPE)
84     {
85       error ("`headof' applied to non-pointer type");
86       return error_mark_node;
87     }
88   type = TREE_TYPE (type);
89
90   if (!TYPE_VIRTUAL_P (type))
91     return exp;
92
93   /* If we don't have rtti stuff, get to a sub-object that does.  */
94   if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
95     exp = build_headof_sub (exp);
96
97   /* We use this a couple of times below, protect it.  */
98   exp = save_expr (exp);
99
100   aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
101
102   if (flag_vtable_thunks)
103     offset = aref;
104   else
105     offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
106
107   type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
108                              TREE_THIS_VOLATILE (exp));
109   return build (PLUS_EXPR, type, exp,
110                 convert (ptrdiff_type_node, offset));
111 }
112
113 /* Build a call to a generic entry point taking and returning void.  */
114
115 static tree
116 call_void_fn (name)
117      char *name;
118 {
119   tree d = get_identifier (name);
120   tree type;
121   
122   if (IDENTIFIER_GLOBAL_VALUE (d))
123     d = IDENTIFIER_GLOBAL_VALUE (d);
124   else
125     {
126       push_obstacks (&permanent_obstack, &permanent_obstack);
127
128       type = build_function_type (void_type_node, void_list_node);
129       d = build_lang_decl (FUNCTION_DECL, d, type);
130       DECL_EXTERNAL (d) = 1;
131       TREE_PUBLIC (d) = 1;
132       DECL_ARTIFICIAL (d) = 1;
133       pushdecl_top_level (d);
134       make_function_rtl (d);
135       assemble_external (d);
136
137       pop_obstacks ();
138     }
139
140   return build_call (d, void_type_node, NULL_TREE);
141 }
142
143 /* Get a bad_cast node for the program to throw...
144
145    See libstdc++/exception.cc for __throw_bad_cast */
146
147 static tree
148 throw_bad_cast ()
149 {
150   return call_void_fn ("__throw_bad_cast");
151 }
152
153 static tree
154 throw_bad_typeid ()
155 {
156   return call_void_fn ("__throw_bad_typeid");
157 }
158 \f
159 /* Return the type_info function associated with the expression EXP.  If
160    EXP is a reference to a polymorphic class, return the dynamic type;
161    otherwise return the static type of the expression.  */
162
163 tree
164 get_tinfo_fn_dynamic (exp)
165      tree exp;
166 {
167   tree type;
168
169   if (exp == error_mark_node)
170     return error_mark_node;
171
172   if (type_unknown_p (exp))
173     {
174       error ("typeid of overloaded function");
175       return error_mark_node;
176     }
177
178   type = TREE_TYPE (exp);
179
180   /* peel back references, so they match.  */
181   if (TREE_CODE (type) == REFERENCE_TYPE)
182     type = TREE_TYPE (type);
183
184   /* Peel off cv qualifiers.  */
185   type = TYPE_MAIN_VARIANT (type);
186
187   /* If exp is a reference to polymorphic type, get the real type_info.  */
188   if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
189     {
190       /* build reference to type_info from vtable.  */
191       tree t;
192
193       if (! flag_rtti)
194         warning ("taking dynamic typeid of object without -frtti");
195
196       /* If we don't have rtti stuff, get to a sub-object that does.  */
197       if (! CLASSTYPE_VFIELDS (type))
198         {
199           exp = build_unary_op (ADDR_EXPR, exp, 0);
200           exp = build_headof_sub (exp);
201           exp = build_indirect_ref (exp, NULL_PTR);
202         }
203
204       if (flag_vtable_thunks)
205         t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
206       else
207         t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
208       TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
209       return t;
210     }
211
212   /* otherwise return the type_info for the static type of the expr.  */
213   return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
214 }
215
216 tree
217 build_typeid (exp)
218      tree exp;
219 {
220   exp = get_tinfo_fn_dynamic (exp);
221   exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
222   return convert_from_reference (exp);
223 }  
224
225 tree
226 build_x_typeid (exp)
227      tree exp;
228 {
229   tree cond = NULL_TREE;
230   tree type = TREE_TYPE (tinfo_fn_type);
231   int nonnull;
232
233   if (processing_template_decl)
234     return build_min_nt (TYPEID_EXPR, exp);
235
236   if (TREE_CODE (exp) == INDIRECT_REF
237       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
238       && TYPE_VIRTUAL_P (TREE_TYPE (exp))
239       && ! resolves_to_fixed_type_p (exp, &nonnull)
240       && ! nonnull)
241     {
242       exp = stabilize_reference (exp);
243       cond = convert (boolean_type_node, TREE_OPERAND (exp, 0));
244     }
245
246   exp = get_tinfo_fn_dynamic (exp);
247
248   if (exp == error_mark_node)
249     return error_mark_node;
250
251   exp = build_call (exp, type, NULL_TREE);
252
253   if (cond)
254     {
255       tree bad = throw_bad_typeid ();
256
257       bad = build_compound_expr
258         (tree_cons (NULL_TREE, bad, build_tree_list
259                     (NULL_TREE, convert (type, integer_zero_node))));
260       exp = build (COND_EXPR, type, cond, exp, bad);
261     }
262
263   return convert_from_reference (exp);
264 }
265
266 static tree
267 get_tinfo_var (type)
268      tree type;
269 {
270   tree tname = build_overload_with_type (get_identifier ("__ti"), type);
271   tree tdecl, arrtype;
272   int size;
273
274   if (IDENTIFIER_GLOBAL_VALUE (tname))
275     return IDENTIFIER_GLOBAL_VALUE (tname);
276     
277   /* Figure out how much space we need to allocate for the type_info object.
278      If our struct layout or the type_info classes are changed, this will
279      need to be modified.  */
280   if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
281     size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
282   else if (TREE_CODE (type) == POINTER_TYPE
283            && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
284                  || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
285     size = 3 * POINTER_SIZE;
286   else if (IS_AGGR_TYPE (type))
287     {
288       if (CLASSTYPE_N_BASECLASSES (type) == 0)
289         size = 2 * POINTER_SIZE;
290       else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
291                && (TREE_VIA_PUBLIC
292                    (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
293         size = 3 * POINTER_SIZE;
294       else
295         size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
296     }
297   else
298     size = 2 * POINTER_SIZE;
299
300   push_obstacks (&permanent_obstack, &permanent_obstack);
301
302   /* The type for a character array of the appropriate size.  */
303   arrtype = build_cplus_array_type
304     (unsigned_char_type_node,
305      build_index_type (size_int (size / BITS_PER_UNIT - 1)));
306
307   tdecl = build_decl (VAR_DECL, tname, arrtype);
308   TREE_PUBLIC (tdecl) = 1;
309   DECL_EXTERNAL (tdecl) = 1;
310   DECL_ARTIFICIAL (tdecl) = 1;
311   pushdecl_top_level (tdecl);
312   cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
313
314   pop_obstacks ();
315
316   return tdecl;
317 }
318
319 tree
320 get_tinfo_fn (type)
321      tree type;
322 {
323   tree name;
324   tree d;
325
326   if (TREE_CODE (type) == OFFSET_TYPE)
327     type = TREE_TYPE (type);
328   if (TREE_CODE (type) == METHOD_TYPE)
329     type = build_function_type (TREE_TYPE (type),
330                                 TREE_CHAIN (TYPE_ARG_TYPES (type)));
331
332   name = build_overload_with_type (tinfo_fn_id, type);
333
334   if (IDENTIFIER_GLOBAL_VALUE (name))
335     return IDENTIFIER_GLOBAL_VALUE (name);
336
337   push_obstacks (&permanent_obstack, &permanent_obstack);
338
339   d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
340   DECL_EXTERNAL (d) = 1;
341   TREE_PUBLIC (d) = 1;
342   DECL_ARTIFICIAL (d) = 1;
343   DECL_NOT_REALLY_EXTERN (d) = 1;
344   DECL_MUTABLE_P (d) = 1;
345   TREE_TYPE (name) = copy_to_permanent (type);
346   pushdecl_top_level (d);
347   make_function_rtl (d);
348   assemble_external (d);
349   mark_inline_for_output (d);
350   if (at_eof)
351     import_export_decl (d);
352
353   pop_obstacks ();
354
355   return d;
356 }
357
358 static tree
359 get_typeid_1 (type)
360      tree type;
361 {
362   tree t = build_call
363     (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
364   return convert_from_reference (t);
365 }
366   
367 /* Return the type_info object for TYPE, creating it if necessary.  */
368
369 tree
370 get_typeid (type)
371      tree type;
372 {
373   if (type == error_mark_node)
374     return error_mark_node;
375   
376   if (processing_template_decl)
377     return build_min_nt (TYPEID_EXPR, type);
378
379   /* If the type of the type-id is a reference type, the result of the
380      typeid expression refers to a type_info object representing the
381      referenced type.  */
382   if (TREE_CODE (type) == REFERENCE_TYPE)
383     type = TREE_TYPE (type);
384
385   /* The top-level cv-qualifiers of the lvalue expression or the type-id
386      that is the operand of typeid are always ignored.  */
387   type = TYPE_MAIN_VARIANT (type);
388
389   return get_typeid_1 (type);
390 }
391
392 /* Check whether TEST is null before returning RESULT.  If TEST is used in
393    RESULT, it must have previously had a save_expr applied to it.  */
394
395 static tree
396 ifnonnull (test, result)
397      tree test, result;
398 {
399   return build (COND_EXPR, TREE_TYPE (result),
400                 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
401                 convert (TREE_TYPE (result), integer_zero_node),
402                 result);
403 }
404
405 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
406    paper.  */
407
408 tree
409 build_dynamic_cast (type, expr)
410      tree type, expr;
411 {
412   enum tree_code tc = TREE_CODE (type);
413   tree exprtype = TREE_TYPE (expr);
414   enum tree_code ec;
415   tree dcast_fn;
416
417   if (type == error_mark_node || expr == error_mark_node)
418     return error_mark_node;
419   
420   if (processing_template_decl)
421     {
422       tree t = build_min (DYNAMIC_CAST_EXPR, type, expr);
423       return t;
424     }
425
426   assert (exprtype != NULL_TREE);
427   ec = TREE_CODE (exprtype);
428
429   switch (tc)
430     {
431     case POINTER_TYPE:
432       if (ec == REFERENCE_TYPE)
433         {
434           expr = convert_from_reference (expr);
435           exprtype = TREE_TYPE (expr);
436           ec = TREE_CODE (exprtype);
437         }
438       if (ec != POINTER_TYPE)
439         goto fail;
440       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
441         goto fail;
442       if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
443         goto fail;
444       if (TREE_READONLY (TREE_TYPE (exprtype))
445           && ! TYPE_READONLY (TREE_TYPE (type)))
446         goto fail;
447       if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
448         break;
449       /* else fall through */
450     case REFERENCE_TYPE:
451       if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
452         goto fail;
453       if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
454         goto fail;
455       break;
456       /* else fall through */
457     default:
458       goto fail;
459     }
460
461   /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
462   if (ec == RECORD_TYPE)
463     {
464       exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
465                                      TREE_THIS_VOLATILE (expr));
466       exprtype = build_reference_type (exprtype);
467       expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
468                                    LOOKUP_NORMAL, NULL_TREE);
469       ec = REFERENCE_TYPE;
470     }
471
472   if (tc == REFERENCE_TYPE)
473     {
474       if (ec != REFERENCE_TYPE)
475         goto fail;
476       if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
477         goto fail;
478       if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
479         goto fail;
480       if (TREE_READONLY (TREE_TYPE (exprtype))
481           && ! TYPE_READONLY (TREE_TYPE (type)))
482         goto fail;
483     }
484
485   /* If *type is an unambiguous accessible base class of *exprtype,
486      convert statically.  */
487   {
488     int distance;
489     tree path;
490
491     distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
492                                   &path);
493     if (distance >= 0)
494       return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
495   }
496
497   /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */
498   if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
499     {
500       tree expr1;
501       /* if TYPE is `void *', return pointer to complete object.  */
502       if (tc == POINTER_TYPE
503           && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
504         {
505           /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b.  */
506           if (TREE_CODE (expr) == ADDR_EXPR
507               && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
508               && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
509             return build1 (NOP_EXPR, type, expr);
510
511           /* Since expr is used twice below, save it.  */
512           expr = save_expr (expr);
513
514           expr1 = build_headof (expr);
515           if (TREE_TYPE (expr1) != type)
516             expr1 = build1 (NOP_EXPR, type, expr1);
517           return ifnonnull (expr, expr1);
518         }
519       else
520         {
521           tree retval;
522           tree result, td1, td2, td3, elems, expr2;
523
524           /* If we got here, we can't convert statically.  Therefore,
525              dynamic_cast<D&>(b) (b an object) cannot succeed.  */
526           if (ec == REFERENCE_TYPE)
527             {
528               if (TREE_CODE (expr) == VAR_DECL
529                   && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
530                 {
531                   cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
532                               expr, type);
533                   return throw_bad_cast ();
534                 }
535             }
536           /* Ditto for dynamic_cast<D*>(&b).  */
537           else if (TREE_CODE (expr) == ADDR_EXPR)
538             {
539               tree op = TREE_OPERAND (expr, 0);
540               if (TREE_CODE (op) == VAR_DECL
541                   && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
542                 {
543                   cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
544                               expr, type);
545                   retval = build_int_2 (0, 0); 
546                   TREE_TYPE (retval) = type; 
547                   return retval;
548                 }
549             }
550
551           /* Since expr is used twice below, save it.  */
552           expr = save_expr (expr);
553
554           expr1 = expr;
555           if (tc == REFERENCE_TYPE)
556             expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
557
558           /* Build run-time conversion.  */
559           expr2 = build_headof (expr1);
560
561           if (ec == POINTER_TYPE)
562             td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
563           else
564             td1 = get_tinfo_fn_dynamic (expr);
565           td1 = decay_conversion (td1);
566           
567           td2 = decay_conversion
568             (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
569           td3 = decay_conversion
570             (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
571
572           elems = tree_cons
573             (NULL_TREE, td1, tree_cons
574              (NULL_TREE, td2, tree_cons
575               (NULL_TREE, build_int_2 (1, 0), tree_cons
576                (NULL_TREE, expr2, tree_cons
577                 (NULL_TREE, td3, tree_cons
578                  (NULL_TREE, expr1, NULL_TREE))))));
579
580           dcast_fn = get_identifier ("__dynamic_cast");
581           if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
582             dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
583           else
584             {
585               tree tmp;
586
587               push_obstacks (&permanent_obstack, &permanent_obstack);
588               tmp = tree_cons
589                 (NULL_TREE, TREE_TYPE (td1), tree_cons
590                  (NULL_TREE, TREE_TYPE (td1), tree_cons
591                   (NULL_TREE, integer_type_node, tree_cons
592                    (NULL_TREE, ptr_type_node, tree_cons
593                     (NULL_TREE, TREE_TYPE (td1), tree_cons
594                      (NULL_TREE, ptr_type_node, void_list_node))))));
595               tmp = build_function_type (ptr_type_node, tmp);
596               dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
597               DECL_EXTERNAL (dcast_fn) = 1;
598               TREE_PUBLIC (dcast_fn) = 1;
599               DECL_ARTIFICIAL (dcast_fn) = 1;
600               pushdecl_top_level (dcast_fn);
601               make_function_rtl (dcast_fn);
602               assemble_external (dcast_fn);
603               pop_obstacks ();
604             }
605           
606           result = build_call
607             (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
608
609           if (tc == REFERENCE_TYPE)
610             {
611               expr1 = throw_bad_cast ();
612               expr1 = build_compound_expr
613                 (tree_cons (NULL_TREE, expr1,
614                             build_tree_list (NULL_TREE, convert
615                                              (type, integer_zero_node))));
616               TREE_TYPE (expr1) = type;
617               result = save_expr (result);
618               return build (COND_EXPR, type, result, result, expr1);
619             }
620
621           /* Now back to the type we want from a void*.  */
622           result = convert (type, result);
623           return ifnonnull (expr, result);
624         }
625     }
626
627  fail:
628   cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
629             expr, exprtype, type);
630   return error_mark_node;
631 }
632 \f
633 /* Build and initialize various sorts of descriptors.  Every descriptor
634    node has a name associated with it (the name created by mangling).
635    For this reason, we use the identifier as our access to the __*_desc
636    nodes, instead of sticking them directly in the types.  Otherwise we
637    would burden all built-in types (and pointer types) with slots that
638    we don't necessarily want to use.
639
640    For each descriptor we build, we build a variable that contains
641    the descriptor's information.  When we need this info at runtime,
642    all we need is access to these variables.
643
644    Note: these constructors always return the address of the descriptor
645    info, since that is simplest for their mutual interaction.  */
646
647 extern tree const_string_type_node;
648
649 /* Build an initializer for a __si_type_info node.  */
650
651 static void
652 expand_si_desc (tdecl, type)
653      tree tdecl;
654      tree type;
655 {
656   tree t, elems, fn;
657   char *name = build_overload_name (type, 1, 1);
658   tree name_string = combine_strings (build_string (strlen (name)+1, name));
659
660   type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
661   expand_expr_stmt (get_typeid_1 (type));
662   t = decay_conversion (get_tinfo_var (type));
663   elems = tree_cons
664     (NULL_TREE, decay_conversion (tdecl), tree_cons
665      (NULL_TREE, decay_conversion (name_string), tree_cons
666       (NULL_TREE, t, NULL_TREE)));
667
668   fn = get_identifier ("__rtti_si");
669   if (IDENTIFIER_GLOBAL_VALUE (fn))
670     fn = IDENTIFIER_GLOBAL_VALUE (fn);
671   else
672     {
673       tree tmp;
674       push_obstacks (&permanent_obstack, &permanent_obstack);
675       tmp = tree_cons
676         (NULL_TREE, ptr_type_node, tree_cons
677          (NULL_TREE, const_string_type_node, tree_cons
678           (NULL_TREE, build_pointer_type (type_info_type_node),
679            void_list_node)));
680       tmp = build_function_type (void_type_node, tmp);
681   
682       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
683       DECL_EXTERNAL (fn) = 1;
684       TREE_PUBLIC (fn) = 1;
685       DECL_ARTIFICIAL (fn) = 1;
686       pushdecl_top_level (fn);
687       make_function_rtl (fn);
688       assemble_external (fn);
689       pop_obstacks ();
690     }
691
692   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
693   expand_expr_stmt (fn);
694 }
695
696 /* Build an initializer for a __class_type_info node.  */
697
698 static void
699 expand_class_desc (tdecl, type)
700      tree tdecl;
701      tree type;
702 {
703   tree name_string;
704   tree fn, tmp;
705   char *name;
706
707   int i = CLASSTYPE_N_BASECLASSES (type);
708   int base_cnt = 0;
709   tree binfos = TYPE_BINFO_BASETYPES (type);
710 #if 0
711   /* See code below that used these.  */
712   tree vb = CLASSTYPE_VBASECLASSES (type);
713   int n_base = i;
714 #endif
715   tree base, elems, access, offset, isvir;
716   tree elt, elts = NULL_TREE;
717   static tree base_info_type_node;
718
719   if (base_info_type_node == NULL_TREE)
720     {
721       tree fields [4];
722
723       /* A reasonably close approximation of __class_type_info::base_info */
724
725       push_obstacks (&permanent_obstack, &permanent_obstack);
726       base_info_type_node = make_lang_type (RECORD_TYPE);
727
728       /* Actually const __user_type_info * */
729       fields [0] = build_lang_field_decl
730         (FIELD_DECL, NULL_TREE,
731          build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
732       fields [1] = build_lang_field_decl
733         (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
734       DECL_BIT_FIELD (fields[1]) = 1;
735       DECL_FIELD_SIZE (fields[1]) = 29;
736
737       fields [2] = build_lang_field_decl
738         (FIELD_DECL, NULL_TREE, boolean_type_node);
739       DECL_BIT_FIELD (fields[2]) = 1;
740       DECL_FIELD_SIZE (fields[2]) = 1;
741
742       /* Actually enum access */
743       fields [3] = build_lang_field_decl
744         (FIELD_DECL, NULL_TREE, integer_type_node);
745       DECL_BIT_FIELD (fields[3]) = 1;
746       DECL_FIELD_SIZE (fields[3]) = 2;
747
748       finish_builtin_type (base_info_type_node, "__base_info", fields,
749                            3, ptr_type_node);
750       pop_obstacks ();
751     }
752
753   while (--i >= 0)
754     {
755       tree binfo = TREE_VEC_ELT (binfos, i);
756
757       expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
758       base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
759
760       if (TREE_VIA_VIRTUAL (binfo))
761         {
762           tree t = BINFO_TYPE (binfo);
763           char *name;
764           tree field;
765
766           name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
767           sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
768           field = lookup_field (type, get_identifier (name), 0, 0);
769           offset = size_binop (FLOOR_DIV_EXPR, 
770                 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
771         }
772       else
773         offset = BINFO_OFFSET (binfo);
774
775       if (TREE_VIA_PUBLIC (binfo))
776         access = access_public_node;
777       else if (TREE_VIA_PROTECTED (binfo))
778         access = access_protected_node;
779       else
780         access = access_private_node;
781       if (TREE_VIA_VIRTUAL (binfo))
782         isvir = boolean_true_node;
783       else
784         isvir = boolean_false_node;
785
786       elt = build
787         (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
788          (NULL_TREE, base, tree_cons
789           (NULL_TREE, offset, tree_cons
790            (NULL_TREE, isvir, tree_cons
791             (NULL_TREE, access, NULL_TREE)))));
792       TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
793       elts = tree_cons (NULL_TREE, elt, elts);
794       base_cnt++;
795     }
796 #if 0
797   i = n_base;
798   while (vb)
799     {
800       tree b;
801       access = access_public_node;
802       while (--i >= 0)
803         {
804           b = TREE_VEC_ELT (binfos, i);
805           if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
806             {
807               if (TREE_VIA_PUBLIC (b))
808                 access = access_public_node;
809               else if (TREE_VIA_PROTECTED (b))
810                 access = access_protected_node;
811               else
812                 access = access_private_node;
813               break;
814             }
815         }
816       base = build_t_desc (BINFO_TYPE (vb), 1);
817       offset = BINFO_OFFSET (vb);
818       isvir = build_int_2 (1, 0);
819
820       base_list = tree_cons (NULL_TREE, base, base_list);
821       isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
822       acc_list = tree_cons (NULL_TREE, access, acc_list);
823       off_list = tree_cons (NULL_TREE, offset, off_list);
824
825       base_cnt++;
826       vb = TREE_CHAIN (vb);
827     }
828 #endif
829
830   name = build_overload_name (type, 1, 1);
831   name_string = combine_strings (build_string (strlen (name)+1, name));
832
833   {
834     tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
835     elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
836     TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
837       = TREE_STATIC (elts) = 1;
838     complete_array_type (arrtype, elts, 1);
839   }
840
841   elems = tree_cons
842     (NULL_TREE, decay_conversion (tdecl), tree_cons
843      (NULL_TREE, decay_conversion (name_string), tree_cons
844       (NULL_TREE, decay_conversion (elts), tree_cons
845        (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))));
846
847   fn = get_identifier ("__rtti_class");
848   if (IDENTIFIER_GLOBAL_VALUE (fn))
849     fn = IDENTIFIER_GLOBAL_VALUE (fn);
850   else
851     {
852       push_obstacks (&permanent_obstack, &permanent_obstack);
853       tmp = tree_cons
854         (NULL_TREE, ptr_type_node, tree_cons
855          (NULL_TREE, const_string_type_node, tree_cons
856           (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
857            (NULL_TREE, sizetype, void_list_node))));
858       tmp = build_function_type (void_type_node, tmp);
859   
860       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
861       DECL_EXTERNAL (fn) = 1;
862       TREE_PUBLIC (fn) = 1;
863       DECL_ARTIFICIAL (fn) = 1;
864       pushdecl_top_level (fn);
865       make_function_rtl (fn);
866       assemble_external (fn);
867       pop_obstacks ();
868     }
869
870   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
871   expand_expr_stmt (fn);
872 }
873
874 /* Build an initializer for a __pointer_type_info node.  */
875
876 static void
877 expand_ptr_desc (tdecl, type)
878      tree tdecl;
879      tree type;
880 {
881   tree t, elems, fn;
882   char *name = build_overload_name (type, 1, 1);
883   tree name_string = combine_strings (build_string (strlen (name)+1, name));
884
885   type = TREE_TYPE (type);
886   expand_expr_stmt (get_typeid_1 (type));
887   t = decay_conversion (get_tinfo_var (type));
888   elems = tree_cons
889     (NULL_TREE, decay_conversion (tdecl), tree_cons
890      (NULL_TREE, decay_conversion (name_string), tree_cons
891       (NULL_TREE, t, NULL_TREE)));
892
893   fn = get_identifier ("__rtti_ptr");
894   if (IDENTIFIER_GLOBAL_VALUE (fn))
895     fn = IDENTIFIER_GLOBAL_VALUE (fn);
896   else
897     {
898       tree tmp;
899       push_obstacks (&permanent_obstack, &permanent_obstack);
900       tmp = tree_cons
901         (NULL_TREE, ptr_type_node, tree_cons
902          (NULL_TREE, const_string_type_node, tree_cons
903           (NULL_TREE, build_pointer_type (type_info_type_node),
904            void_list_node)));
905       tmp = build_function_type (void_type_node, tmp);
906   
907       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
908       DECL_EXTERNAL (fn) = 1;
909       TREE_PUBLIC (fn) = 1;
910       DECL_ARTIFICIAL (fn) = 1;
911       pushdecl_top_level (fn);
912       make_function_rtl (fn);
913       assemble_external (fn);
914       pop_obstacks ();
915     }
916
917   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
918   expand_expr_stmt (fn);
919 }
920
921 /* Build an initializer for a __attr_type_info node.  */
922
923 static void
924 expand_attr_desc (tdecl, type)
925      tree tdecl;
926      tree type;
927 {
928   tree elems, t, fn;
929   char *name = build_overload_name (type, 1, 1);
930   tree name_string = combine_strings (build_string (strlen (name)+1, name));
931   tree attrval = build_int_2
932     (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
933
934   expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
935   t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
936   elems = tree_cons
937     (NULL_TREE, decay_conversion (tdecl), tree_cons
938      (NULL_TREE, decay_conversion (name_string), tree_cons
939       (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
940
941   fn = get_identifier ("__rtti_attr");
942   if (IDENTIFIER_GLOBAL_VALUE (fn))
943     fn = IDENTIFIER_GLOBAL_VALUE (fn);
944   else
945     {
946       tree tmp;
947       push_obstacks (&permanent_obstack, &permanent_obstack);
948       tmp = tree_cons
949         (NULL_TREE, ptr_type_node, tree_cons
950          (NULL_TREE, const_string_type_node, tree_cons
951           (NULL_TREE, integer_type_node, tree_cons
952            (NULL_TREE, build_pointer_type (type_info_type_node),
953             void_list_node))));
954       tmp = build_function_type (void_type_node, tmp);
955   
956       fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
957       DECL_EXTERNAL (fn) = 1;
958       TREE_PUBLIC (fn) = 1;
959       DECL_ARTIFICIAL (fn) = 1;
960       pushdecl_top_level (fn);
961       make_function_rtl (fn);
962       assemble_external (fn);
963       pop_obstacks ();
964     }
965
966   fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
967   expand_expr_stmt (fn);
968 }
969
970 /* Build an initializer for a type_info node that just has a name.  */
971
972 static void
973 expand_generic_desc (tdecl, type, fnname)
974      tree tdecl;
975      tree type;
976      char *fnname;
977 {
978   char *name = build_overload_name (type, 1, 1);
979   tree name_string = combine_strings (build_string (strlen (name)+1, name));
980   tree elems = tree_cons
981     (NULL_TREE, decay_conversion (tdecl), tree_cons
982      (NULL_TREE, decay_conversion (name_string), NULL_TREE));
983
984   tree fn = get_identifier (fnname);
985   if (IDENTIFIER_GLOBAL_VALUE (fn))
986     fn = IDENTIFIER_GLOBAL_VALUE (fn);
987   else
988     {
989       tree tmp;
990       push_obstacks (&permanent_obstack, &permanent_obstack);
991       tmp = tree_cons
992         (NULL_TREE, ptr_type_node, tree_cons
993          (NULL_TREE, const_string_type_node, 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 /* Generate the code for a type_info initialization function.
1011    Note that we take advantage of the passage
1012
1013    5.2.7  Type identification                               [expr.typeid]
1014    
1015    Whether or not the destructor is called for the type_info object at the
1016    end of the program is unspecified.
1017
1018    and don't bother to arrange for these objects to be destroyed.  It
1019    doesn't matter, anyway, since the destructors don't do anything.
1020        
1021    This must only be called from toplevel (i.e. from finish_file)!  */
1022
1023 void
1024 synthesize_tinfo_fn (fndecl)
1025      tree fndecl;
1026 {
1027   tree type = TREE_TYPE (DECL_NAME (fndecl));
1028   tree tmp, addr;
1029
1030   tree tdecl = get_tinfo_var (type);
1031   DECL_EXTERNAL (tdecl) = 0;
1032   TREE_STATIC (tdecl) = 1;
1033   DECL_COMMON (tdecl) = 1;
1034   TREE_USED (tdecl) = 1;
1035   DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1036   cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1037
1038   start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1039   store_parm_decls ();
1040   clear_last_expr ();
1041   push_momentary ();
1042
1043   /* If the first word of the array (the vtable) is non-zero, we've already
1044      initialized the object, so don't do it again.  */
1045   addr = decay_conversion (tdecl);
1046   tmp = convert (build_pointer_type (ptr_type_node), addr);
1047   tmp = build_indirect_ref (tmp, 0);
1048   tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1049   expand_start_cond (tmp, 0);
1050
1051   if (TREE_CODE (type) == FUNCTION_TYPE)
1052     expand_generic_desc (tdecl, type, "__rtti_func");
1053   else if (TREE_CODE (type) == ARRAY_TYPE)
1054     expand_generic_desc (tdecl, type, "__rtti_array");
1055   else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1056     expand_attr_desc (tdecl, type);
1057   else if (TREE_CODE (type) == POINTER_TYPE)
1058     {
1059       if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1060         expand_generic_desc (tdecl, type, "__rtti_ptmd");
1061       else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1062         expand_generic_desc (tdecl, type, "__rtti_ptmf");
1063       else
1064         expand_ptr_desc (tdecl, type);
1065     }
1066   else if (TYPE_PTRMEMFUNC_P (type))
1067     expand_generic_desc (tdecl, type, "__rtti_ptmf");
1068   else if (IS_AGGR_TYPE (type))
1069     {
1070       if (CLASSTYPE_N_BASECLASSES (type) == 0)
1071         expand_generic_desc (tdecl, type, "__rtti_user");
1072       else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1073                && (TREE_VIA_PUBLIC
1074                    (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1075         expand_si_desc (tdecl, type);
1076       else
1077         expand_class_desc (tdecl, type);
1078     }
1079   else if (TREE_CODE (type) == ENUMERAL_TYPE)
1080     expand_generic_desc (tdecl, type, "__rtti_user");
1081   else
1082     my_friendly_abort (252);
1083
1084   expand_end_cond ();
1085
1086   /* OK, now return the type_info object.  */
1087   tmp = convert (build_pointer_type (type_info_type_node), addr);
1088   tmp = build_indirect_ref (tmp, 0);
1089   c_expand_return (tmp);
1090   finish_function (lineno, 0, 0);
1091 }
1092
1093 #if 0
1094 /* This is the old dossier type descriptor generation code, it's much
1095    more extended than rtti. It's reserved for later use.  */
1096 /* Build an initializer for a __t_desc node.  So that we can take advantage
1097    of recursion, we accept NULL for TYPE.
1098    DEFINITION is greater than zero iff we must define the type descriptor
1099    (as opposed to merely referencing it).  1 means treat according to
1100    #pragma interface/#pragma implementation rules.  2 means define as
1101    global and public, no matter what.  */
1102
1103 tree
1104 build_t_desc (type, definition)
1105      tree type;
1106      int definition;
1107 {
1108   tree tdecl;
1109   tree tname, name_string;
1110   tree elems, fields;
1111   tree parents, vbases, offsets, ivars, methods, target_type;
1112   int method_count = 0, field_count = 0;
1113
1114   if (type == NULL_TREE)
1115     return NULL_TREE;
1116
1117   tname = build_t_desc_overload (type);
1118   if (IDENTIFIER_AS_DESC (tname)
1119       && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1120     return IDENTIFIER_AS_DESC (tname);
1121
1122   tdecl = lookup_name (tname, 0);
1123   if (tdecl == NULL_TREE)
1124     {
1125       tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1126       DECL_EXTERNAL (tdecl) = 1;
1127       TREE_PUBLIC (tdecl) = 1;
1128       tdecl = pushdecl_top_level (tdecl);
1129     }
1130   /* If we previously defined it, return the defined result.  */
1131   else if (definition && DECL_INITIAL (tdecl))
1132     return IDENTIFIER_AS_DESC (tname);
1133
1134   if (definition)
1135     {
1136       tree taggr = type;
1137       /* Let T* and T& be written only when T is written (if T is an aggr).
1138          We do this for const, but not for volatile, since volatile
1139          is rare and const is not.  */
1140       if (!TYPE_VOLATILE (taggr)
1141           && (TREE_CODE (taggr) == POINTER_TYPE
1142               || TREE_CODE (taggr) == REFERENCE_TYPE)
1143           && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1144         taggr = TREE_TYPE (taggr);
1145
1146       /* If we know that we don't need to write out this type's
1147          vtable, then don't write out it's dossier.  Somebody
1148          else will take care of that.  */
1149       if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1150         {
1151           if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1152             {
1153               TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1154                 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1155               DECL_EXTERNAL (tdecl) = 0;
1156             }
1157           else
1158             {
1159               if (write_virtuals != 0)
1160                 TREE_PUBLIC (tdecl) = 1;
1161             }
1162         }
1163       else
1164         {
1165           DECL_EXTERNAL (tdecl) = 0;
1166           TREE_PUBLIC (tdecl) = (definition > 1);
1167         }
1168     }
1169   SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1170
1171   if (!definition || DECL_EXTERNAL (tdecl))
1172     {
1173       /* That's it!  */
1174       cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1175       return IDENTIFIER_AS_DESC (tname);
1176     }
1177
1178   /* Show that we are defining the t_desc for this type.  */
1179   DECL_INITIAL (tdecl) = error_mark_node;
1180
1181   parents = build_tree_list (NULL_TREE, integer_zero_node);
1182   vbases = build_tree_list (NULL_TREE, integer_zero_node);
1183   offsets = build_tree_list (NULL_TREE, integer_zero_node);
1184   methods = NULL_TREE;
1185   ivars = NULL_TREE;
1186
1187   if (TYPE_LANG_SPECIFIC (type))
1188     {
1189       int i = CLASSTYPE_N_BASECLASSES (type);
1190       tree method_vec = CLASSTYPE_METHOD_VEC (type);
1191       tree *meth, *end;
1192       tree binfos = TYPE_BINFO_BASETYPES (type);
1193       tree vb = CLASSTYPE_VBASECLASSES (type);
1194
1195       while (--i >= 0)
1196         parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1197
1198       while (vb)
1199         {
1200           vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1201           offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1202           vb = TREE_CHAIN (vb);
1203         }
1204
1205       if (method_vec)
1206         for (meth = TREE_VEC_END (method_vec),
1207              end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1208           if (*meth)
1209             {
1210               methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1211               method_count++;
1212             }
1213     }
1214
1215   if (IS_AGGR_TYPE (type))
1216     {
1217       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1218         if (TREE_CODE (fields) == FIELD_DECL
1219             || TREE_CODE (fields) == VAR_DECL)
1220           {
1221             ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1222             field_count++;
1223           }
1224       ivars = nreverse (ivars);
1225     }
1226
1227   parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1228   vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1229   offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1230   if (methods == NULL_TREE)
1231     methods = null_pointer_node;
1232   else
1233     methods = build_unary_op (ADDR_EXPR,
1234                               finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1235                               0);
1236   if (ivars == NULL_TREE)
1237     ivars = null_pointer_node;
1238   else
1239     ivars = build_unary_op (ADDR_EXPR,
1240                             finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1241                             0);
1242   if (TREE_TYPE (type))
1243     target_type = build_t_desc (TREE_TYPE (type), definition);
1244   else
1245     target_type = integer_zero_node;
1246
1247   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1248
1249   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1250            tree_cons (NULL_TREE,
1251                       TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1252              /* really should use bitfield initialization here.  */
1253              tree_cons (NULL_TREE, integer_zero_node,
1254               tree_cons (NULL_TREE, target_type,
1255                tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1256                 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1257                  tree_cons (NULL_TREE, ivars,
1258                   tree_cons (NULL_TREE, methods,
1259                    tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1260                     tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1261                      build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1262   return build_generic_desc (tdecl, elems);
1263 }
1264
1265 /* Build an initializer for a __i_desc node.  */
1266
1267 tree
1268 build_i_desc (decl)
1269      tree decl;
1270 {
1271   tree elems, name_string;
1272   tree taggr;
1273
1274   name_string = DECL_NAME (decl);
1275   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1276
1277   /* Now decide whether this ivar should cause it's type to get
1278      def'd or ref'd in this file.  If the type we are looking at
1279      has a proxy definition, we look at the proxy (i.e., a
1280      `foo *' is equivalent to a `foo').  */
1281   taggr = TREE_TYPE (decl);
1282
1283   if ((TREE_CODE (taggr) == POINTER_TYPE
1284        || TREE_CODE (taggr) == REFERENCE_TYPE)
1285       && TYPE_VOLATILE (taggr) == 0)
1286     taggr = TREE_TYPE (taggr);
1287
1288   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1289              tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1290                 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1291                                                           ! IS_AGGR_TYPE (taggr)))));
1292   taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1293   TREE_CONSTANT (taggr) = 1;
1294   TREE_STATIC (taggr) = 1;
1295   TREE_READONLY (taggr) = 1;
1296   return taggr;
1297 }
1298
1299 /* Build an initializer for a __m_desc node.  */
1300
1301 tree
1302 build_m_desc (decl)
1303      tree decl;
1304 {
1305   tree taggr, elems, name_string;
1306   tree parm_count, req_count, vindex, vcontext;
1307   tree parms;
1308   int p_count, r_count;
1309   tree parm_types = NULL_TREE;
1310
1311   for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1312        parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1313     {
1314       taggr = TREE_VALUE (parms);
1315       if ((TREE_CODE (taggr) == POINTER_TYPE
1316            || TREE_CODE (taggr) == REFERENCE_TYPE)
1317           && TYPE_VOLATILE (taggr) == 0)
1318         taggr = TREE_TYPE (taggr);
1319
1320       parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1321                                                        ! IS_AGGR_TYPE (taggr)),
1322                               parm_types);
1323       if (TREE_PURPOSE (parms) == NULL_TREE)
1324         r_count++;
1325     }
1326
1327   parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1328                              nreverse (parm_types), 0);
1329   parm_count = build_int_2 (p_count, 0);
1330   req_count = build_int_2 (r_count, 0);
1331
1332   if (DECL_VINDEX (decl))
1333     vindex = DECL_VINDEX (decl);
1334   else
1335     vindex = integer_zero_node;
1336   if (DECL_CONTEXT (decl)
1337       && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1338     vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1339   else
1340     vcontext = integer_zero_node;
1341   name_string = DECL_NAME (decl);
1342   if (name_string == NULL)
1343       name_string = DECL_ASSEMBLER_NAME (decl);
1344   name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1345
1346   /* Now decide whether the return type of this mvar
1347      should cause it's type to get def'd or ref'd in this file.
1348      If the type we are looking at has a proxy definition,
1349      we look at the proxy (i.e., a `foo *' is equivalent to a `foo').  */
1350   taggr = TREE_TYPE (TREE_TYPE (decl));
1351
1352   if ((TREE_CODE (taggr) == POINTER_TYPE
1353        || TREE_CODE (taggr) == REFERENCE_TYPE)
1354       && TYPE_VOLATILE (taggr) == 0)
1355     taggr = TREE_TYPE (taggr);
1356
1357   elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1358              tree_cons (NULL_TREE, vindex,
1359                 tree_cons (NULL_TREE, vcontext,
1360                    tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1361                                                        ! IS_AGGR_TYPE (taggr)),
1362                       tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
1363                          tree_cons (NULL_TREE, parm_count,
1364                             tree_cons (NULL_TREE, req_count,
1365                                build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1366
1367   taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1368   TREE_CONSTANT (taggr) = 1;
1369   TREE_STATIC (taggr) = 1;
1370   TREE_READONLY (taggr) = 1;
1371   return taggr;
1372 }
1373 #endif /* dossier */