OSDN Git Service

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