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