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