86th Cygnus<->FSF quick merge
[gcc.git] / gcc / cp / rtti.c
1 /* RunTime Type Identification
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
3 Mostly written by Jason Merrill (jason@cygnus.com).
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22
23 #include "config.h"
24 #include "tree.h"
25 #include "cp-tree.h"
26 #include "flags.h"
27 #include "output.h"
28
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 */