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)
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. */
32 extern tree define_function ();
33 extern tree build_t_desc_overload ();
34 extern struct obstack *permanent_obstack;
36 tree type_info_type_node;
41 extern tree combine_strings PROTO((tree));
44 init_rtti_processing ()
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)),
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
59 build_headof_sub (exp)
62 tree type = TREE_TYPE (TREE_TYPE (exp));
63 tree basetype = CLASSTYPE_RTTI (type);
64 tree binfo = get_binfo (basetype, type, 0);
66 exp = convert_pointer_to_real (binfo, exp);
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
78 tree type = TREE_TYPE (exp);
82 if (TREE_CODE (type) != POINTER_TYPE)
84 error ("`headof' applied to non-pointer type");
85 return error_mark_node;
87 type = TREE_TYPE (type);
89 if (!TYPE_VIRTUAL_P (type))
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);
96 /* We use this a couple of times below, protect it. */
97 exp = save_expr (exp);
99 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
101 if (flag_vtable_thunks)
104 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
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));
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. */
121 if (exp == error_mark_node)
122 return error_mark_node;
124 type = TREE_TYPE (exp);
126 /* Strip top-level cv-qualifiers. */
127 type = TYPE_MAIN_VARIANT (type);
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);
134 /* peel back references, so they match. */
135 if (TREE_CODE (type) == REFERENCE_TYPE)
136 type = TREE_TYPE (type);
138 /* Peel off cv qualifiers. */
139 type = TYPE_MAIN_VARIANT (type);
141 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
142 if (TREE_CODE (type) == RECORD_TYPE)
143 type = build_reference_type (type);
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)))
148 /* build reference to type_info from vtable. */
152 warning ("taking dynamic typeid of object without -frtti");
154 /* If we don't have rtti stuff, get to a sub-object that does. */
155 if (!CLASSTYPE_VFIELDS (TREE_TYPE (type)))
157 exp = build_unary_op (ADDR_EXPR, exp, 0);
158 exp = build_headof_sub (exp);
159 exp = build_indirect_ref (exp, NULL_PTR);
162 if (flag_vtable_thunks)
163 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
165 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
166 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
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);
173 /* otherwise return the type_info for the static type of the expr. */
174 return get_typeid (type);
181 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
185 if (IDENTIFIER_GLOBAL_VALUE (tname))
186 return IDENTIFIER_GLOBAL_VALUE (tname);
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))
199 if (CLASSTYPE_N_BASECLASSES (type) == 0)
200 size = 2 * POINTER_SIZE;
201 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
203 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
204 size = 3 * POINTER_SIZE;
206 size = 4 * POINTER_SIZE;
209 size = 2 * POINTER_SIZE;
211 push_obstacks (&permanent_obstack, &permanent_obstack);
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)));
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);
234 tree name = build_overload_with_type (tinfo_fn_id, type);
237 if (IDENTIFIER_GLOBAL_VALUE (name))
238 return IDENTIFIER_GLOBAL_VALUE (name);
240 push_obstacks (&permanent_obstack, &permanent_obstack);
242 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
243 DECL_EXTERNAL (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);
253 import_export_decl (d);
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);
270 /* Return the type_info object for TYPE, creating it if necessary. */
277 if (type == error_mark_node)
278 return error_mark_node;
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
283 if (TREE_CODE (type) == REFERENCE_TYPE)
284 type = TREE_TYPE (type);
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);
290 return get_typeid_1 (type);
293 /* Get a bad_cast node for the program to throw...
295 See libstdc++/exception.cc for __throw_bad_cast */
300 tree d = get_identifier ("__throw_bad_cast");
303 if (IDENTIFIER_GLOBAL_VALUE (d))
304 return IDENTIFIER_GLOBAL_VALUE (d);
306 push_obstacks (&permanent_obstack, &permanent_obstack);
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;
312 DECL_ARTIFICIAL (d) = 1;
313 pushdecl_top_level (d);
314 make_function_rtl (d);
318 d = build (CALL_EXPR, void_type_node, default_conversion (d), NULL_TREE, 0);
319 TREE_SIDE_EFFECTS (d) = 1;
323 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
327 build_dynamic_cast (type, expr)
330 enum tree_code tc = TREE_CODE (type);
331 tree exprtype = TREE_TYPE (expr);
332 enum tree_code ec = TREE_CODE (exprtype);
335 if (type == error_mark_node || expr == error_mark_node)
336 return error_mark_node;
341 if (ec == REFERENCE_TYPE)
343 expr = convert_from_reference (expr);
344 exprtype = TREE_TYPE (expr);
345 ec = TREE_CODE (exprtype);
347 if (ec != POINTER_TYPE)
349 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
351 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
353 if (TREE_READONLY (TREE_TYPE (exprtype)) &&
354 ! TYPE_READONLY (TREE_TYPE (type)))
356 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
358 /* else fall through */
360 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
362 if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
365 /* else fall through */
370 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
371 if (ec == RECORD_TYPE)
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);
381 if (tc == REFERENCE_TYPE)
383 if (ec != REFERENCE_TYPE)
385 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
387 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
389 if (TREE_READONLY (TREE_TYPE (exprtype)) &&
390 ! TYPE_READONLY (TREE_TYPE (type)))
394 /* If *type is an unambiguous accessible base class of *exprtype,
395 convert statically. */
400 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
403 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
406 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
407 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
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)
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);
419 expr = build_headof (expr);
420 if (TREE_TYPE (expr) != type)
421 expr = build1 (NOP_EXPR, type, expr);
427 tree result, td1, td2, td3, elems, expr1, expr2;
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)
433 if (TREE_CODE (expr) == VAR_DECL
434 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
436 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
438 return throw_bad_cast ();
441 /* Ditto for dynamic_cast<D*>(&b). */
442 else if (TREE_CODE (expr) == ADDR_EXPR)
444 tree op = TREE_OPERAND (expr, 0);
445 if (TREE_CODE (op) == VAR_DECL
446 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
448 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
450 retval = build_int_2 (0, 0);
451 TREE_TYPE (retval) = type;
456 /* Since expr is used twice below, save it. */
457 expr = save_expr (expr);
460 if (tc == REFERENCE_TYPE)
461 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
463 /* Build run-time conversion. */
464 expr2 = build_headof (expr1);
466 if (ec == POINTER_TYPE)
467 td1 = build_typeid (build_indirect_ref (expr, NULL_PTR));
469 td1 = build_typeid (expr);
471 td2 = get_typeid (TREE_TYPE (type));
472 td3 = get_typeid (TREE_TYPE (exprtype));
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))))));
482 dcast_fn = get_identifier ("__dynamic_cast");
483 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
484 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
489 push_obstacks (&permanent_obstack, &permanent_obstack);
490 tmp = build_reference_type
491 (build_type_variant (type_info_type_node, 1, 0));
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);
509 result = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (dcast_fn)),
510 decay_conversion (dcast_fn), elems, 0);
511 TREE_SIDE_EFFECTS (result) = 1;
513 if (tc == REFERENCE_TYPE)
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);
523 /* Now back to the type we want from a void*. */
524 result = convert (type, result);
530 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
531 expr, exprtype, type);
532 return error_mark_node;
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.
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.
546 Note: these constructors always return the address of the descriptor
547 info, since that is simplest for their mutual interaction. */
549 extern tree const_string_type_node;
551 /* Build an initializer for a __si_type_info node. */
554 expand_si_desc (tdecl, type)
559 char *name = build_overload_name (type, 1, 1);
560 tree name_string = combine_strings (build_string (strlen (name), name));
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));
566 (NULL_TREE, decay_conversion (tdecl), tree_cons
567 (NULL_TREE, decay_conversion (name_string), tree_cons
568 (NULL_TREE, t, NULL_TREE)));
570 fn = get_identifier ("__rtti_si");
571 if (IDENTIFIER_GLOBAL_VALUE (fn))
572 fn = IDENTIFIER_GLOBAL_VALUE (fn);
576 push_obstacks (&permanent_obstack, &permanent_obstack);
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),
582 tmp = build_function_type (void_type_node, tmp);
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);
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);
599 /* Build an initializer for a __class_type_info node. */
602 expand_class_desc (tdecl, type)
606 tree tname = TYPE_NESTED_NAME (type);
611 int i = CLASSTYPE_N_BASECLASSES (type);
613 tree binfos = TYPE_BINFO_BASETYPES (type);
615 /* See code below that used these. */
616 tree vb = CLASSTYPE_VBASECLASSES (type);
619 tree base, elems, access, offset, isvir;
620 tree elt, elts = NULL_TREE;
621 static tree base_info_type_node;
623 if (base_info_type_node == NULL_TREE)
627 /* A reasonably close approximation of __class_type_info::base_info */
629 push_obstacks (&permanent_obstack, &permanent_obstack);
630 base_info_type_node = make_lang_type (RECORD_TYPE);
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;
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;
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;
652 finish_builtin_type (base_info_type_node, "__base_info", fields,
659 tree binfo = TREE_VEC_ELT (binfos, i);
661 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
662 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
664 if (TREE_VIA_VIRTUAL (binfo))
666 tree t = BINFO_TYPE (binfo);
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));
677 offset = BINFO_OFFSET (binfo);
679 if (TREE_VIA_PUBLIC (binfo))
680 access = access_public_node;
681 else if (TREE_VIA_PROTECTED (binfo))
682 access = access_protected_node;
684 access = access_private_node;
685 if (TREE_VIA_VIRTUAL (binfo))
686 isvir = boolean_true_node;
688 isvir = boolean_false_node;
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);
705 access = access_public_node;
708 b = TREE_VEC_ELT (binfos, i);
709 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
711 if (TREE_VIA_PUBLIC (b))
712 access = access_public_node;
713 else if (TREE_VIA_PROTECTED (b))
714 access = access_protected_node;
716 access = access_private_node;
720 base = build_t_desc (BINFO_TYPE (vb), 1);
721 offset = BINFO_OFFSET (vb);
722 isvir = build_int_2 (1, 0);
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);
730 vb = TREE_CHAIN (vb);
734 name = build_overload_name (type, 1, 1);
735 name_string = combine_strings (build_string (strlen (name), name));
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);
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))));
751 fn = get_identifier ("__rtti_class");
752 if (IDENTIFIER_GLOBAL_VALUE (fn))
753 fn = IDENTIFIER_GLOBAL_VALUE (fn);
756 push_obstacks (&permanent_obstack, &permanent_obstack);
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);
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);
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);
779 /* Build an initializer for a __pointer_type_info node. */
781 expand_ptr_desc (tdecl, type)
786 char *name = build_overload_name (type, 1, 1);
787 tree name_string = combine_strings (build_string (strlen (name), name));
789 type = TREE_TYPE (type);
790 expand_expr_stmt (get_typeid_1 (type));
791 t = decay_conversion (get_tinfo_var (type));
793 (NULL_TREE, decay_conversion (tdecl), tree_cons
794 (NULL_TREE, decay_conversion (name_string), tree_cons
795 (NULL_TREE, t, NULL_TREE)));
797 fn = get_identifier ("__rtti_ptr");
798 if (IDENTIFIER_GLOBAL_VALUE (fn))
799 fn = IDENTIFIER_GLOBAL_VALUE (fn);
803 push_obstacks (&permanent_obstack, &permanent_obstack);
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),
809 tmp = build_function_type (void_type_node, tmp);
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);
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);
826 /* Build an initializer for a __attr_type_info node. */
829 expand_attr_desc (tdecl, type)
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);
839 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
840 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
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))));
846 fn = get_identifier ("__rtti_attr");
847 if (IDENTIFIER_GLOBAL_VALUE (fn))
848 fn = IDENTIFIER_GLOBAL_VALUE (fn);
852 push_obstacks (&permanent_obstack, &permanent_obstack);
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),
859 tmp = build_function_type (void_type_node, tmp);
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);
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);
876 /* Build an initializer for a type_info node that just has a name. */
879 expand_generic_desc (tdecl, type, fnname)
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));
890 tree fn = get_identifier (fnname);
891 if (IDENTIFIER_GLOBAL_VALUE (fn))
892 fn = IDENTIFIER_GLOBAL_VALUE (fn);
896 push_obstacks (&permanent_obstack, &permanent_obstack);
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);
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);
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);
917 /* Generate the code for a type_info initialization function.
918 Note that we take advantage of the passage
920 5.2.7 Type identification [expr.typeid]
922 Whether or not the destructor is called for the type_info object at the
923 end of the program is unspecified.
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.
928 This must only be called from toplevel (i.e. from finish_file)! */
931 synthesize_tinfo_fn (fndecl)
934 tree type = TREE_TYPE (DECL_NAME (fndecl));
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);
945 start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
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);
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)
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");
969 expand_ptr_desc (tdecl, type);
971 else if (TYPE_PTRMEMFUNC_P (type))
972 expand_generic_desc (tdecl, type, "__rtti_ptmf");
973 else if (IS_AGGR_TYPE (type))
975 if (CLASSTYPE_N_BASECLASSES (type) == 0)
976 expand_generic_desc (tdecl, type, "__rtti_user");
977 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
979 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
980 expand_si_desc (tdecl, type);
982 expand_class_desc (tdecl, type);
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");
989 my_friendly_abort (252);
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);
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. */
1010 build_t_desc (type, definition)
1015 tree tname, name_string;
1017 tree parents, vbases, offsets, ivars, methods, target_type;
1018 int method_count = 0, field_count = 0;
1020 if (type == NULL_TREE)
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);
1028 tdecl = lookup_name (tname, 0);
1029 if (tdecl == NULL_TREE)
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);
1036 /* If we previously defined it, return the defined result. */
1037 else if (definition && DECL_INITIAL (tdecl))
1038 return IDENTIFIER_AS_DESC (tname);
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);
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))
1057 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1059 TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1060 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1061 DECL_EXTERNAL (tdecl) = 0;
1065 if (write_virtuals != 0)
1066 TREE_PUBLIC (tdecl) = 1;
1071 DECL_EXTERNAL (tdecl) = 0;
1072 TREE_PUBLIC (tdecl) = (definition > 1);
1075 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1077 if (!definition || DECL_EXTERNAL (tdecl))
1080 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1081 return IDENTIFIER_AS_DESC (tname);
1084 /* Show that we are defining the t_desc for this type. */
1085 DECL_INITIAL (tdecl) = error_mark_node;
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;
1093 if (TYPE_LANG_SPECIFIC (type))
1095 int i = CLASSTYPE_N_BASECLASSES (type);
1096 tree method_vec = CLASSTYPE_METHOD_VEC (type);
1098 tree binfos = TYPE_BINFO_BASETYPES (type);
1099 tree vb = CLASSTYPE_VBASECLASSES (type);
1102 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
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);
1112 for (meth = TREE_VEC_END (method_vec),
1113 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1116 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1121 if (IS_AGGR_TYPE (type))
1123 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1124 if (TREE_CODE (fields) == FIELD_DECL
1125 || TREE_CODE (fields) == VAR_DECL)
1127 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1130 ivars = nreverse (ivars);
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;
1139 methods = build_unary_op (ADDR_EXPR,
1140 finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1142 if (ivars == NULL_TREE)
1143 ivars = null_pointer_node;
1145 ivars = build_unary_op (ADDR_EXPR,
1146 finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1148 if (TREE_TYPE (type))
1149 target_type = build_t_desc (TREE_TYPE (type), definition);
1151 target_type = integer_zero_node;
1153 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
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);
1171 /* Build an initializer for a __i_desc node. */
1176 tree elems, name_string;
1179 name_string = DECL_NAME (decl);
1180 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
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);
1188 if ((TREE_CODE (taggr) == POINTER_TYPE
1189 || TREE_CODE (taggr) == REFERENCE_TYPE)
1190 && TYPE_VOLATILE (taggr) == 0)
1191 taggr = TREE_TYPE (taggr);
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;
1204 /* Build an initializer for a __m_desc node. */
1209 tree taggr, elems, name_string;
1210 tree parm_count, req_count, vindex, vcontext;
1212 int p_count, r_count;
1213 tree parm_types = NULL_TREE;
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++)
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);
1224 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1225 ! IS_AGGR_TYPE (taggr)),
1227 if (TREE_PURPOSE (parms) == NULL_TREE)
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);
1236 if (DECL_VINDEX (decl))
1237 vindex = DECL_VINDEX (decl);
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);
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)));
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));
1256 if ((TREE_CODE (taggr) == POINTER_TYPE
1257 || TREE_CODE (taggr) == REFERENCE_TYPE)
1258 && TYPE_VOLATILE (taggr) == 0)
1259 taggr = TREE_TYPE (taggr);
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)))))))));
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;
1277 #endif /* dossier */