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. */
31 #define INT_TYPE_SIZE BITS_PER_WORD
34 extern tree define_function ();
35 extern tree build_t_desc_overload ();
36 extern struct obstack *permanent_obstack;
38 tree type_info_type_node;
43 init_rtti_processing ()
45 type_info_type_node = xref_tag
46 (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
47 tinfo_fn_id = get_identifier ("__tf");
48 tinfo_fn_type = build_function_type
49 (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
53 /* Given a pointer to an object with at least one virtual table
54 pointer somewhere, return a pointer to a possible sub-object that
55 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
79 tree type = TREE_TYPE (exp);
83 if (TREE_CODE (type) != POINTER_TYPE)
85 error ("`headof' applied to non-pointer type");
86 return error_mark_node;
88 type = TREE_TYPE (type);
90 if (!TYPE_VIRTUAL_P (type))
93 /* If we don't have rtti stuff, get to a sub-object that does. */
94 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
95 exp = build_headof_sub (exp);
97 /* We use this a couple of times below, protect it. */
98 exp = save_expr (exp);
100 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
102 if (flag_vtable_thunks)
105 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
107 type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
108 TREE_THIS_VOLATILE (exp));
109 return build (PLUS_EXPR, type, exp,
110 convert (ptrdiff_type_node, offset));
113 /* Build a call to a generic entry point taking and returning void. */
119 tree d = get_identifier (name);
122 if (IDENTIFIER_GLOBAL_VALUE (d))
123 d = IDENTIFIER_GLOBAL_VALUE (d);
126 push_obstacks (&permanent_obstack, &permanent_obstack);
128 type = build_function_type (void_type_node, void_list_node);
129 d = build_lang_decl (FUNCTION_DECL, d, type);
130 DECL_EXTERNAL (d) = 1;
132 DECL_ARTIFICIAL (d) = 1;
133 pushdecl_top_level (d);
134 make_function_rtl (d);
135 assemble_external (d);
140 return build_call (d, void_type_node, NULL_TREE);
143 /* Get a bad_cast node for the program to throw...
145 See libstdc++/exception.cc for __throw_bad_cast */
150 return call_void_fn ("__throw_bad_cast");
156 return call_void_fn ("__throw_bad_typeid");
159 /* Return the type_info function associated with the expression EXP. If
160 EXP is a reference to a polymorphic class, return the dynamic type;
161 otherwise return the static type of the expression. */
164 get_tinfo_fn_dynamic (exp)
169 if (exp == error_mark_node)
170 return error_mark_node;
172 if (type_unknown_p (exp))
174 error ("typeid of overloaded function");
175 return error_mark_node;
178 type = TREE_TYPE (exp);
180 /* peel back references, so they match. */
181 if (TREE_CODE (type) == REFERENCE_TYPE)
182 type = TREE_TYPE (type);
184 /* Peel off cv qualifiers. */
185 type = TYPE_MAIN_VARIANT (type);
187 /* If exp is a reference to polymorphic type, get the real type_info. */
188 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
190 /* build reference to type_info from vtable. */
194 warning ("taking dynamic typeid of object without -frtti");
196 /* If we don't have rtti stuff, get to a sub-object that does. */
197 if (! CLASSTYPE_VFIELDS (type))
199 exp = build_unary_op (ADDR_EXPR, exp, 0);
200 exp = build_headof_sub (exp);
201 exp = build_indirect_ref (exp, NULL_PTR);
204 if (flag_vtable_thunks)
205 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
207 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
208 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
212 /* otherwise return the type_info for the static type of the expr. */
213 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
220 exp = get_tinfo_fn_dynamic (exp);
221 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
222 return convert_from_reference (exp);
229 tree cond = NULL_TREE;
230 tree type = TREE_TYPE (tinfo_fn_type);
233 if (processing_template_decl)
234 return build_min_nt (TYPEID_EXPR, exp);
236 if (TREE_CODE (exp) == INDIRECT_REF
237 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
238 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
239 && ! resolves_to_fixed_type_p (exp, &nonnull)
242 exp = stabilize_reference (exp);
243 cond = convert (boolean_type_node, TREE_OPERAND (exp, 0));
246 exp = get_tinfo_fn_dynamic (exp);
248 if (exp == error_mark_node)
249 return error_mark_node;
251 exp = build_call (exp, type, NULL_TREE);
255 tree bad = throw_bad_typeid ();
257 bad = build_compound_expr
258 (tree_cons (NULL_TREE, bad, build_tree_list
259 (NULL_TREE, convert (type, integer_zero_node))));
260 exp = build (COND_EXPR, type, cond, exp, bad);
263 return convert_from_reference (exp);
270 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
274 if (IDENTIFIER_GLOBAL_VALUE (tname))
275 return IDENTIFIER_GLOBAL_VALUE (tname);
277 /* Figure out how much space we need to allocate for the type_info object.
278 If our struct layout or the type_info classes are changed, this will
279 need to be modified. */
280 if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
281 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
282 else if (TREE_CODE (type) == POINTER_TYPE
283 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
284 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
285 size = 3 * POINTER_SIZE;
286 else if (IS_AGGR_TYPE (type))
288 if (CLASSTYPE_N_BASECLASSES (type) == 0)
289 size = 2 * POINTER_SIZE;
290 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
292 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
293 size = 3 * POINTER_SIZE;
295 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
298 size = 2 * POINTER_SIZE;
300 push_obstacks (&permanent_obstack, &permanent_obstack);
302 /* The type for a character array of the appropriate size. */
303 arrtype = build_cplus_array_type
304 (unsigned_char_type_node,
305 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
307 tdecl = build_decl (VAR_DECL, tname, arrtype);
308 TREE_PUBLIC (tdecl) = 1;
309 DECL_EXTERNAL (tdecl) = 1;
310 DECL_ARTIFICIAL (tdecl) = 1;
311 pushdecl_top_level (tdecl);
312 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
326 if (TREE_CODE (type) == OFFSET_TYPE)
327 type = TREE_TYPE (type);
328 if (TREE_CODE (type) == METHOD_TYPE)
329 type = build_function_type (TREE_TYPE (type),
330 TREE_CHAIN (TYPE_ARG_TYPES (type)));
332 name = build_overload_with_type (tinfo_fn_id, type);
334 if (IDENTIFIER_GLOBAL_VALUE (name))
335 return IDENTIFIER_GLOBAL_VALUE (name);
337 push_obstacks (&permanent_obstack, &permanent_obstack);
339 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
340 DECL_EXTERNAL (d) = 1;
342 DECL_ARTIFICIAL (d) = 1;
343 DECL_NOT_REALLY_EXTERN (d) = 1;
344 DECL_MUTABLE_P (d) = 1;
345 TREE_TYPE (name) = copy_to_permanent (type);
346 pushdecl_top_level (d);
347 make_function_rtl (d);
348 assemble_external (d);
349 mark_inline_for_output (d);
351 import_export_decl (d);
363 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
364 return convert_from_reference (t);
367 /* Return the type_info object for TYPE, creating it if necessary. */
373 if (type == error_mark_node)
374 return error_mark_node;
376 if (processing_template_decl)
377 return build_min_nt (TYPEID_EXPR, type);
379 /* If the type of the type-id is a reference type, the result of the
380 typeid expression refers to a type_info object representing the
382 if (TREE_CODE (type) == REFERENCE_TYPE)
383 type = TREE_TYPE (type);
385 /* The top-level cv-qualifiers of the lvalue expression or the type-id
386 that is the operand of typeid are always ignored. */
387 type = TYPE_MAIN_VARIANT (type);
389 return get_typeid_1 (type);
392 /* Check whether TEST is null before returning RESULT. If TEST is used in
393 RESULT, it must have previously had a save_expr applied to it. */
396 ifnonnull (test, result)
399 return build (COND_EXPR, TREE_TYPE (result),
400 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
401 convert (TREE_TYPE (result), integer_zero_node),
405 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
409 build_dynamic_cast (type, expr)
412 enum tree_code tc = TREE_CODE (type);
413 tree exprtype = TREE_TYPE (expr);
417 if (type == error_mark_node || expr == error_mark_node)
418 return error_mark_node;
420 if (processing_template_decl)
422 tree t = build_min (DYNAMIC_CAST_EXPR, type, expr);
426 assert (exprtype != NULL_TREE);
427 ec = TREE_CODE (exprtype);
432 if (ec == REFERENCE_TYPE)
434 expr = convert_from_reference (expr);
435 exprtype = TREE_TYPE (expr);
436 ec = TREE_CODE (exprtype);
438 if (ec != POINTER_TYPE)
440 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
442 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
444 if (TREE_READONLY (TREE_TYPE (exprtype))
445 && ! TYPE_READONLY (TREE_TYPE (type)))
447 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
449 /* else fall through */
451 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
453 if (TYPE_SIZE (TREE_TYPE (type)) == NULL_TREE)
456 /* else fall through */
461 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
462 if (ec == RECORD_TYPE)
464 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
465 TREE_THIS_VOLATILE (expr));
466 exprtype = build_reference_type (exprtype);
467 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
468 LOOKUP_NORMAL, NULL_TREE);
472 if (tc == REFERENCE_TYPE)
474 if (ec != REFERENCE_TYPE)
476 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
478 if (TYPE_SIZE (TREE_TYPE (exprtype)) == NULL_TREE)
480 if (TREE_READONLY (TREE_TYPE (exprtype))
481 && ! TYPE_READONLY (TREE_TYPE (type)))
485 /* If *type is an unambiguous accessible base class of *exprtype,
486 convert statically. */
491 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
494 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
497 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
498 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
501 /* if TYPE is `void *', return pointer to complete object. */
502 if (tc == POINTER_TYPE
503 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
505 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
506 if (TREE_CODE (expr) == ADDR_EXPR
507 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
508 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
509 return build1 (NOP_EXPR, type, expr);
511 /* Since expr is used twice below, save it. */
512 expr = save_expr (expr);
514 expr1 = build_headof (expr);
515 if (TREE_TYPE (expr1) != type)
516 expr1 = build1 (NOP_EXPR, type, expr1);
517 return ifnonnull (expr, expr1);
522 tree result, td1, td2, td3, elems, expr2;
524 /* If we got here, we can't convert statically. Therefore,
525 dynamic_cast<D&>(b) (b an object) cannot succeed. */
526 if (ec == REFERENCE_TYPE)
528 if (TREE_CODE (expr) == VAR_DECL
529 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
531 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
533 return throw_bad_cast ();
536 /* Ditto for dynamic_cast<D*>(&b). */
537 else if (TREE_CODE (expr) == ADDR_EXPR)
539 tree op = TREE_OPERAND (expr, 0);
540 if (TREE_CODE (op) == VAR_DECL
541 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
543 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
545 retval = build_int_2 (0, 0);
546 TREE_TYPE (retval) = type;
551 /* Since expr is used twice below, save it. */
552 expr = save_expr (expr);
555 if (tc == REFERENCE_TYPE)
556 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
558 /* Build run-time conversion. */
559 expr2 = build_headof (expr1);
561 if (ec == POINTER_TYPE)
562 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
564 td1 = get_tinfo_fn_dynamic (expr);
565 td1 = decay_conversion (td1);
567 td2 = decay_conversion
568 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
569 td3 = decay_conversion
570 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
573 (NULL_TREE, td1, tree_cons
574 (NULL_TREE, td2, tree_cons
575 (NULL_TREE, build_int_2 (1, 0), tree_cons
576 (NULL_TREE, expr2, tree_cons
577 (NULL_TREE, td3, tree_cons
578 (NULL_TREE, expr1, NULL_TREE))))));
580 dcast_fn = get_identifier ("__dynamic_cast");
581 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
582 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
587 push_obstacks (&permanent_obstack, &permanent_obstack);
589 (NULL_TREE, TREE_TYPE (td1), tree_cons
590 (NULL_TREE, TREE_TYPE (td1), tree_cons
591 (NULL_TREE, integer_type_node, tree_cons
592 (NULL_TREE, ptr_type_node, tree_cons
593 (NULL_TREE, TREE_TYPE (td1), tree_cons
594 (NULL_TREE, ptr_type_node, void_list_node))))));
595 tmp = build_function_type (ptr_type_node, tmp);
596 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
597 DECL_EXTERNAL (dcast_fn) = 1;
598 TREE_PUBLIC (dcast_fn) = 1;
599 DECL_ARTIFICIAL (dcast_fn) = 1;
600 pushdecl_top_level (dcast_fn);
601 make_function_rtl (dcast_fn);
602 assemble_external (dcast_fn);
607 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
609 if (tc == REFERENCE_TYPE)
611 expr1 = throw_bad_cast ();
612 expr1 = build_compound_expr
613 (tree_cons (NULL_TREE, expr1,
614 build_tree_list (NULL_TREE, convert
615 (type, integer_zero_node))));
616 TREE_TYPE (expr1) = type;
617 result = save_expr (result);
618 return build (COND_EXPR, type, result, result, expr1);
621 /* Now back to the type we want from a void*. */
622 result = convert (type, result);
623 return ifnonnull (expr, result);
628 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
629 expr, exprtype, type);
630 return error_mark_node;
633 /* Build and initialize various sorts of descriptors. Every descriptor
634 node has a name associated with it (the name created by mangling).
635 For this reason, we use the identifier as our access to the __*_desc
636 nodes, instead of sticking them directly in the types. Otherwise we
637 would burden all built-in types (and pointer types) with slots that
638 we don't necessarily want to use.
640 For each descriptor we build, we build a variable that contains
641 the descriptor's information. When we need this info at runtime,
642 all we need is access to these variables.
644 Note: these constructors always return the address of the descriptor
645 info, since that is simplest for their mutual interaction. */
647 extern tree const_string_type_node;
649 /* Build an initializer for a __si_type_info node. */
652 expand_si_desc (tdecl, type)
657 char *name = build_overload_name (type, 1, 1);
658 tree name_string = combine_strings (build_string (strlen (name)+1, name));
660 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
661 expand_expr_stmt (get_typeid_1 (type));
662 t = decay_conversion (get_tinfo_var (type));
664 (NULL_TREE, decay_conversion (tdecl), tree_cons
665 (NULL_TREE, decay_conversion (name_string), tree_cons
666 (NULL_TREE, t, NULL_TREE)));
668 fn = get_identifier ("__rtti_si");
669 if (IDENTIFIER_GLOBAL_VALUE (fn))
670 fn = IDENTIFIER_GLOBAL_VALUE (fn);
674 push_obstacks (&permanent_obstack, &permanent_obstack);
676 (NULL_TREE, ptr_type_node, tree_cons
677 (NULL_TREE, const_string_type_node, tree_cons
678 (NULL_TREE, build_pointer_type (type_info_type_node),
680 tmp = build_function_type (void_type_node, tmp);
682 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
683 DECL_EXTERNAL (fn) = 1;
684 TREE_PUBLIC (fn) = 1;
685 DECL_ARTIFICIAL (fn) = 1;
686 pushdecl_top_level (fn);
687 make_function_rtl (fn);
688 assemble_external (fn);
692 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
693 expand_expr_stmt (fn);
696 /* Build an initializer for a __class_type_info node. */
699 expand_class_desc (tdecl, type)
707 int i = CLASSTYPE_N_BASECLASSES (type);
709 tree binfos = TYPE_BINFO_BASETYPES (type);
711 /* See code below that used these. */
712 tree vb = CLASSTYPE_VBASECLASSES (type);
715 tree base, elems, access, offset, isvir;
716 tree elt, elts = NULL_TREE;
717 static tree base_info_type_node;
719 if (base_info_type_node == NULL_TREE)
723 /* A reasonably close approximation of __class_type_info::base_info */
725 push_obstacks (&permanent_obstack, &permanent_obstack);
726 base_info_type_node = make_lang_type (RECORD_TYPE);
728 /* Actually const __user_type_info * */
729 fields [0] = build_lang_field_decl
730 (FIELD_DECL, NULL_TREE,
731 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
732 fields [1] = build_lang_field_decl
733 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
734 DECL_BIT_FIELD (fields[1]) = 1;
735 DECL_FIELD_SIZE (fields[1]) = 29;
737 fields [2] = build_lang_field_decl
738 (FIELD_DECL, NULL_TREE, boolean_type_node);
739 DECL_BIT_FIELD (fields[2]) = 1;
740 DECL_FIELD_SIZE (fields[2]) = 1;
742 /* Actually enum access */
743 fields [3] = build_lang_field_decl
744 (FIELD_DECL, NULL_TREE, integer_type_node);
745 DECL_BIT_FIELD (fields[3]) = 1;
746 DECL_FIELD_SIZE (fields[3]) = 2;
748 finish_builtin_type (base_info_type_node, "__base_info", fields,
755 tree binfo = TREE_VEC_ELT (binfos, i);
757 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
758 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
760 if (TREE_VIA_VIRTUAL (binfo))
762 tree t = BINFO_TYPE (binfo);
766 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
767 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
768 field = lookup_field (type, get_identifier (name), 0, 0);
769 offset = size_binop (FLOOR_DIV_EXPR,
770 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
773 offset = BINFO_OFFSET (binfo);
775 if (TREE_VIA_PUBLIC (binfo))
776 access = access_public_node;
777 else if (TREE_VIA_PROTECTED (binfo))
778 access = access_protected_node;
780 access = access_private_node;
781 if (TREE_VIA_VIRTUAL (binfo))
782 isvir = boolean_true_node;
784 isvir = boolean_false_node;
787 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
788 (NULL_TREE, base, tree_cons
789 (NULL_TREE, offset, tree_cons
790 (NULL_TREE, isvir, tree_cons
791 (NULL_TREE, access, NULL_TREE)))));
792 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
793 elts = tree_cons (NULL_TREE, elt, elts);
801 access = access_public_node;
804 b = TREE_VEC_ELT (binfos, i);
805 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
807 if (TREE_VIA_PUBLIC (b))
808 access = access_public_node;
809 else if (TREE_VIA_PROTECTED (b))
810 access = access_protected_node;
812 access = access_private_node;
816 base = build_t_desc (BINFO_TYPE (vb), 1);
817 offset = BINFO_OFFSET (vb);
818 isvir = build_int_2 (1, 0);
820 base_list = tree_cons (NULL_TREE, base, base_list);
821 isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
822 acc_list = tree_cons (NULL_TREE, access, acc_list);
823 off_list = tree_cons (NULL_TREE, offset, off_list);
826 vb = TREE_CHAIN (vb);
830 name = build_overload_name (type, 1, 1);
831 name_string = combine_strings (build_string (strlen (name)+1, name));
834 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
835 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
836 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
837 = TREE_STATIC (elts) = 1;
838 complete_array_type (arrtype, elts, 1);
842 (NULL_TREE, decay_conversion (tdecl), tree_cons
843 (NULL_TREE, decay_conversion (name_string), tree_cons
844 (NULL_TREE, decay_conversion (elts), tree_cons
845 (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))));
847 fn = get_identifier ("__rtti_class");
848 if (IDENTIFIER_GLOBAL_VALUE (fn))
849 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, build_pointer_type (base_info_type_node), tree_cons
857 (NULL_TREE, sizetype, void_list_node))));
858 tmp = build_function_type (void_type_node, tmp);
860 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
861 DECL_EXTERNAL (fn) = 1;
862 TREE_PUBLIC (fn) = 1;
863 DECL_ARTIFICIAL (fn) = 1;
864 pushdecl_top_level (fn);
865 make_function_rtl (fn);
866 assemble_external (fn);
870 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
871 expand_expr_stmt (fn);
874 /* Build an initializer for a __pointer_type_info node. */
877 expand_ptr_desc (tdecl, type)
882 char *name = build_overload_name (type, 1, 1);
883 tree name_string = combine_strings (build_string (strlen (name)+1, name));
885 type = TREE_TYPE (type);
886 expand_expr_stmt (get_typeid_1 (type));
887 t = decay_conversion (get_tinfo_var (type));
889 (NULL_TREE, decay_conversion (tdecl), tree_cons
890 (NULL_TREE, decay_conversion (name_string), tree_cons
891 (NULL_TREE, t, NULL_TREE)));
893 fn = get_identifier ("__rtti_ptr");
894 if (IDENTIFIER_GLOBAL_VALUE (fn))
895 fn = IDENTIFIER_GLOBAL_VALUE (fn);
899 push_obstacks (&permanent_obstack, &permanent_obstack);
901 (NULL_TREE, ptr_type_node, tree_cons
902 (NULL_TREE, const_string_type_node, tree_cons
903 (NULL_TREE, build_pointer_type (type_info_type_node),
905 tmp = build_function_type (void_type_node, tmp);
907 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
908 DECL_EXTERNAL (fn) = 1;
909 TREE_PUBLIC (fn) = 1;
910 DECL_ARTIFICIAL (fn) = 1;
911 pushdecl_top_level (fn);
912 make_function_rtl (fn);
913 assemble_external (fn);
917 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
918 expand_expr_stmt (fn);
921 /* Build an initializer for a __attr_type_info node. */
924 expand_attr_desc (tdecl, type)
929 char *name = build_overload_name (type, 1, 1);
930 tree name_string = combine_strings (build_string (strlen (name)+1, name));
931 tree attrval = build_int_2
932 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
934 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
935 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
937 (NULL_TREE, decay_conversion (tdecl), tree_cons
938 (NULL_TREE, decay_conversion (name_string), tree_cons
939 (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
941 fn = get_identifier ("__rtti_attr");
942 if (IDENTIFIER_GLOBAL_VALUE (fn))
943 fn = IDENTIFIER_GLOBAL_VALUE (fn);
947 push_obstacks (&permanent_obstack, &permanent_obstack);
949 (NULL_TREE, ptr_type_node, tree_cons
950 (NULL_TREE, const_string_type_node, tree_cons
951 (NULL_TREE, integer_type_node, tree_cons
952 (NULL_TREE, build_pointer_type (type_info_type_node),
954 tmp = build_function_type (void_type_node, tmp);
956 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
957 DECL_EXTERNAL (fn) = 1;
958 TREE_PUBLIC (fn) = 1;
959 DECL_ARTIFICIAL (fn) = 1;
960 pushdecl_top_level (fn);
961 make_function_rtl (fn);
962 assemble_external (fn);
966 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
967 expand_expr_stmt (fn);
970 /* Build an initializer for a type_info node that just has a name. */
973 expand_generic_desc (tdecl, type, fnname)
978 char *name = build_overload_name (type, 1, 1);
979 tree name_string = combine_strings (build_string (strlen (name)+1, name));
980 tree elems = tree_cons
981 (NULL_TREE, decay_conversion (tdecl), tree_cons
982 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
984 tree fn = get_identifier (fnname);
985 if (IDENTIFIER_GLOBAL_VALUE (fn))
986 fn = IDENTIFIER_GLOBAL_VALUE (fn);
990 push_obstacks (&permanent_obstack, &permanent_obstack);
992 (NULL_TREE, ptr_type_node, tree_cons
993 (NULL_TREE, const_string_type_node, void_list_node));
994 tmp = build_function_type (void_type_node, tmp);
996 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
997 DECL_EXTERNAL (fn) = 1;
998 TREE_PUBLIC (fn) = 1;
999 DECL_ARTIFICIAL (fn) = 1;
1000 pushdecl_top_level (fn);
1001 make_function_rtl (fn);
1002 assemble_external (fn);
1006 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1007 expand_expr_stmt (fn);
1010 /* Generate the code for a type_info initialization function.
1011 Note that we take advantage of the passage
1013 5.2.7 Type identification [expr.typeid]
1015 Whether or not the destructor is called for the type_info object at the
1016 end of the program is unspecified.
1018 and don't bother to arrange for these objects to be destroyed. It
1019 doesn't matter, anyway, since the destructors don't do anything.
1021 This must only be called from toplevel (i.e. from finish_file)! */
1024 synthesize_tinfo_fn (fndecl)
1027 tree type = TREE_TYPE (DECL_NAME (fndecl));
1030 tree tdecl = get_tinfo_var (type);
1031 DECL_EXTERNAL (tdecl) = 0;
1032 TREE_STATIC (tdecl) = 1;
1033 DECL_COMMON (tdecl) = 1;
1034 TREE_USED (tdecl) = 1;
1035 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1036 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1038 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1039 store_parm_decls ();
1043 /* If the first word of the array (the vtable) is non-zero, we've already
1044 initialized the object, so don't do it again. */
1045 addr = decay_conversion (tdecl);
1046 tmp = convert (build_pointer_type (ptr_type_node), addr);
1047 tmp = build_indirect_ref (tmp, 0);
1048 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1049 expand_start_cond (tmp, 0);
1051 if (TREE_CODE (type) == FUNCTION_TYPE)
1052 expand_generic_desc (tdecl, type, "__rtti_func");
1053 else if (TREE_CODE (type) == ARRAY_TYPE)
1054 expand_generic_desc (tdecl, type, "__rtti_array");
1055 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1056 expand_attr_desc (tdecl, type);
1057 else if (TREE_CODE (type) == POINTER_TYPE)
1059 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1060 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1061 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1062 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1064 expand_ptr_desc (tdecl, type);
1066 else if (TYPE_PTRMEMFUNC_P (type))
1067 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1068 else if (IS_AGGR_TYPE (type))
1070 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1071 expand_generic_desc (tdecl, type, "__rtti_user");
1072 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1074 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1075 expand_si_desc (tdecl, type);
1077 expand_class_desc (tdecl, type);
1079 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1080 expand_generic_desc (tdecl, type, "__rtti_user");
1082 my_friendly_abort (252);
1086 /* OK, now return the type_info object. */
1087 tmp = convert (build_pointer_type (type_info_type_node), addr);
1088 tmp = build_indirect_ref (tmp, 0);
1089 c_expand_return (tmp);
1090 finish_function (lineno, 0, 0);
1094 /* This is the old dossier type descriptor generation code, it's much
1095 more extended than rtti. It's reserved for later use. */
1096 /* Build an initializer for a __t_desc node. So that we can take advantage
1097 of recursion, we accept NULL for TYPE.
1098 DEFINITION is greater than zero iff we must define the type descriptor
1099 (as opposed to merely referencing it). 1 means treat according to
1100 #pragma interface/#pragma implementation rules. 2 means define as
1101 global and public, no matter what. */
1104 build_t_desc (type, definition)
1109 tree tname, name_string;
1111 tree parents, vbases, offsets, ivars, methods, target_type;
1112 int method_count = 0, field_count = 0;
1114 if (type == NULL_TREE)
1117 tname = build_t_desc_overload (type);
1118 if (IDENTIFIER_AS_DESC (tname)
1119 && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1120 return IDENTIFIER_AS_DESC (tname);
1122 tdecl = lookup_name (tname, 0);
1123 if (tdecl == NULL_TREE)
1125 tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1126 DECL_EXTERNAL (tdecl) = 1;
1127 TREE_PUBLIC (tdecl) = 1;
1128 tdecl = pushdecl_top_level (tdecl);
1130 /* If we previously defined it, return the defined result. */
1131 else if (definition && DECL_INITIAL (tdecl))
1132 return IDENTIFIER_AS_DESC (tname);
1137 /* Let T* and T& be written only when T is written (if T is an aggr).
1138 We do this for const, but not for volatile, since volatile
1139 is rare and const is not. */
1140 if (!TYPE_VOLATILE (taggr)
1141 && (TREE_CODE (taggr) == POINTER_TYPE
1142 || TREE_CODE (taggr) == REFERENCE_TYPE)
1143 && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1144 taggr = TREE_TYPE (taggr);
1146 /* If we know that we don't need to write out this type's
1147 vtable, then don't write out it's dossier. Somebody
1148 else will take care of that. */
1149 if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1151 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1153 TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1154 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1155 DECL_EXTERNAL (tdecl) = 0;
1159 if (write_virtuals != 0)
1160 TREE_PUBLIC (tdecl) = 1;
1165 DECL_EXTERNAL (tdecl) = 0;
1166 TREE_PUBLIC (tdecl) = (definition > 1);
1169 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1171 if (!definition || DECL_EXTERNAL (tdecl))
1174 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1175 return IDENTIFIER_AS_DESC (tname);
1178 /* Show that we are defining the t_desc for this type. */
1179 DECL_INITIAL (tdecl) = error_mark_node;
1181 parents = build_tree_list (NULL_TREE, integer_zero_node);
1182 vbases = build_tree_list (NULL_TREE, integer_zero_node);
1183 offsets = build_tree_list (NULL_TREE, integer_zero_node);
1184 methods = NULL_TREE;
1187 if (TYPE_LANG_SPECIFIC (type))
1189 int i = CLASSTYPE_N_BASECLASSES (type);
1190 tree method_vec = CLASSTYPE_METHOD_VEC (type);
1192 tree binfos = TYPE_BINFO_BASETYPES (type);
1193 tree vb = CLASSTYPE_VBASECLASSES (type);
1196 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1200 vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1201 offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1202 vb = TREE_CHAIN (vb);
1206 for (meth = TREE_VEC_END (method_vec),
1207 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1210 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1215 if (IS_AGGR_TYPE (type))
1217 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1218 if (TREE_CODE (fields) == FIELD_DECL
1219 || TREE_CODE (fields) == VAR_DECL)
1221 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1224 ivars = nreverse (ivars);
1227 parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1228 vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1229 offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1230 if (methods == NULL_TREE)
1231 methods = null_pointer_node;
1233 methods = build_unary_op (ADDR_EXPR,
1234 finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1236 if (ivars == NULL_TREE)
1237 ivars = null_pointer_node;
1239 ivars = build_unary_op (ADDR_EXPR,
1240 finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1242 if (TREE_TYPE (type))
1243 target_type = build_t_desc (TREE_TYPE (type), definition);
1245 target_type = integer_zero_node;
1247 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1249 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1250 tree_cons (NULL_TREE,
1251 TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1252 /* really should use bitfield initialization here. */
1253 tree_cons (NULL_TREE, integer_zero_node,
1254 tree_cons (NULL_TREE, target_type,
1255 tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1256 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1257 tree_cons (NULL_TREE, ivars,
1258 tree_cons (NULL_TREE, methods,
1259 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1260 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1261 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1262 return build_generic_desc (tdecl, elems);
1265 /* Build an initializer for a __i_desc node. */
1271 tree elems, name_string;
1274 name_string = DECL_NAME (decl);
1275 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1277 /* Now decide whether this ivar should cause it's type to get
1278 def'd or ref'd in this file. If the type we are looking at
1279 has a proxy definition, we look at the proxy (i.e., a
1280 `foo *' is equivalent to a `foo'). */
1281 taggr = TREE_TYPE (decl);
1283 if ((TREE_CODE (taggr) == POINTER_TYPE
1284 || TREE_CODE (taggr) == REFERENCE_TYPE)
1285 && TYPE_VOLATILE (taggr) == 0)
1286 taggr = TREE_TYPE (taggr);
1288 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1289 tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1290 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1291 ! IS_AGGR_TYPE (taggr)))));
1292 taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1293 TREE_CONSTANT (taggr) = 1;
1294 TREE_STATIC (taggr) = 1;
1295 TREE_READONLY (taggr) = 1;
1299 /* Build an initializer for a __m_desc node. */
1305 tree taggr, elems, name_string;
1306 tree parm_count, req_count, vindex, vcontext;
1308 int p_count, r_count;
1309 tree parm_types = NULL_TREE;
1311 for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1312 parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1314 taggr = TREE_VALUE (parms);
1315 if ((TREE_CODE (taggr) == POINTER_TYPE
1316 || TREE_CODE (taggr) == REFERENCE_TYPE)
1317 && TYPE_VOLATILE (taggr) == 0)
1318 taggr = TREE_TYPE (taggr);
1320 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1321 ! IS_AGGR_TYPE (taggr)),
1323 if (TREE_PURPOSE (parms) == NULL_TREE)
1327 parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1328 nreverse (parm_types), 0);
1329 parm_count = build_int_2 (p_count, 0);
1330 req_count = build_int_2 (r_count, 0);
1332 if (DECL_VINDEX (decl))
1333 vindex = DECL_VINDEX (decl);
1335 vindex = integer_zero_node;
1336 if (DECL_CONTEXT (decl)
1337 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1338 vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1340 vcontext = integer_zero_node;
1341 name_string = DECL_NAME (decl);
1342 if (name_string == NULL)
1343 name_string = DECL_ASSEMBLER_NAME (decl);
1344 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1346 /* Now decide whether the return type of this mvar
1347 should cause it's type to get def'd or ref'd in this file.
1348 If the type we are looking at has a proxy definition,
1349 we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
1350 taggr = TREE_TYPE (TREE_TYPE (decl));
1352 if ((TREE_CODE (taggr) == POINTER_TYPE
1353 || TREE_CODE (taggr) == REFERENCE_TYPE)
1354 && TYPE_VOLATILE (taggr) == 0)
1355 taggr = TREE_TYPE (taggr);
1357 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1358 tree_cons (NULL_TREE, vindex,
1359 tree_cons (NULL_TREE, vcontext,
1360 tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1361 ! IS_AGGR_TYPE (taggr)),
1362 tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
1363 tree_cons (NULL_TREE, parm_count,
1364 tree_cons (NULL_TREE, req_count,
1365 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1367 taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1368 TREE_CONSTANT (taggr) = 1;
1369 TREE_STATIC (taggr) = 1;
1370 TREE_READONLY (taggr) = 1;
1373 #endif /* dossier */