OSDN Git Service

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