OSDN Git Service

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