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 #define INT_TYPE_SIZE BITS_PER_WORD
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;
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)),
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
73 build_headof_sub (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);
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
93 tree type = TREE_TYPE (exp);
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))
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)
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. */
133 tree d = get_identifier (name);
136 if (IDENTIFIER_GLOBAL_VALUE (d))
137 d = IDENTIFIER_GLOBAL_VALUE (d);
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;
146 DECL_ARTIFICIAL (d) = 1;
147 pushdecl_top_level (d);
148 make_function_rtl (d);
149 assemble_external (d);
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 */
164 return call_void_fn ("__throw_bad_cast");
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. */
178 get_tinfo_fn_dynamic (exp)
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. */
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);
221 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
222 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
226 /* otherwise return the type_info for the static type of the expr. */
227 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
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);
243 tree cond = NULL_TREE;
244 tree type = TREE_TYPE (tinfo_fn_type);
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)
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);
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);
284 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
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)
306 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
307 size = 3 * POINTER_SIZE;
309 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
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);
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;
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);
365 import_export_decl (d);
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. */
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
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. */
410 ifnonnull (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),
419 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
423 build_dynamic_cast_1 (type, expr)
426 enum tree_code tc = TREE_CODE (type);
427 tree exprtype = TREE_TYPE (expr);
431 assert (exprtype != NULL_TREE);
432 ec = TREE_CODE (exprtype);
437 if (ec == REFERENCE_TYPE)
439 expr = convert_from_reference (expr);
440 exprtype = TREE_TYPE (expr);
441 ec = TREE_CODE (exprtype);
443 if (ec != POINTER_TYPE)
445 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
447 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
449 if (TREE_READONLY (TREE_TYPE (exprtype))
450 && ! TYPE_READONLY (TREE_TYPE (type)))
452 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
454 /* else fall through */
456 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
458 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
461 /* else fall through */
466 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
467 if (ec == RECORD_TYPE)
469 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
470 TREE_THIS_VOLATILE (expr));
471 exprtype = build_reference_type (exprtype);
472 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
473 LOOKUP_NORMAL, NULL_TREE);
477 if (tc == REFERENCE_TYPE)
479 if (ec != REFERENCE_TYPE)
481 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
483 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
485 if (TREE_READONLY (TREE_TYPE (exprtype))
486 && ! TYPE_READONLY (TREE_TYPE (type)))
490 /* If *type is an unambiguous accessible base class of *exprtype,
491 convert statically. */
496 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
499 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
502 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
503 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
506 /* if TYPE is `void *', return pointer to complete object. */
507 if (tc == POINTER_TYPE
508 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
510 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
511 if (TREE_CODE (expr) == ADDR_EXPR
512 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
513 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
514 return build1 (NOP_EXPR, type, expr);
516 /* Since expr is used twice below, save it. */
517 expr = save_expr (expr);
519 expr1 = build_headof (expr);
520 if (TREE_TYPE (expr1) != type)
521 expr1 = build1 (NOP_EXPR, type, expr1);
522 return ifnonnull (expr, expr1);
527 tree result, td1, td2, td3, elems, expr2;
529 /* If we got here, we can't convert statically. Therefore,
530 dynamic_cast<D&>(b) (b an object) cannot succeed. */
531 if (ec == REFERENCE_TYPE)
533 if (TREE_CODE (expr) == VAR_DECL
534 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
536 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
538 return throw_bad_cast ();
541 /* Ditto for dynamic_cast<D*>(&b). */
542 else if (TREE_CODE (expr) == ADDR_EXPR)
544 tree op = TREE_OPERAND (expr, 0);
545 if (TREE_CODE (op) == VAR_DECL
546 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
548 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
550 retval = build_int_2 (0, 0);
551 TREE_TYPE (retval) = type;
556 /* Since expr is used twice below, save it. */
557 expr = save_expr (expr);
560 if (tc == REFERENCE_TYPE)
561 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
563 /* Build run-time conversion. */
564 expr2 = build_headof (expr1);
566 if (ec == POINTER_TYPE)
567 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
569 td1 = get_tinfo_fn_dynamic (expr);
570 td1 = decay_conversion (td1);
572 td2 = decay_conversion
573 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
574 td3 = decay_conversion
575 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
578 (NULL_TREE, td1, tree_cons
579 (NULL_TREE, td2, tree_cons
580 (NULL_TREE, build_int_2 (1, 0), tree_cons
581 (NULL_TREE, expr2, tree_cons
582 (NULL_TREE, td3, tree_cons
583 (NULL_TREE, expr1, NULL_TREE))))));
585 dcast_fn = get_identifier ("__dynamic_cast");
586 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
587 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
592 push_obstacks (&permanent_obstack, &permanent_obstack);
594 (NULL_TREE, TREE_TYPE (td1), tree_cons
595 (NULL_TREE, TREE_TYPE (td1), tree_cons
596 (NULL_TREE, integer_type_node, tree_cons
597 (NULL_TREE, ptr_type_node, tree_cons
598 (NULL_TREE, TREE_TYPE (td1), tree_cons
599 (NULL_TREE, ptr_type_node, void_list_node))))));
600 tmp = build_function_type (ptr_type_node, tmp);
601 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
602 DECL_EXTERNAL (dcast_fn) = 1;
603 TREE_PUBLIC (dcast_fn) = 1;
604 DECL_ARTIFICIAL (dcast_fn) = 1;
605 pushdecl_top_level (dcast_fn);
606 make_function_rtl (dcast_fn);
607 assemble_external (dcast_fn);
612 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
614 if (tc == REFERENCE_TYPE)
616 expr1 = throw_bad_cast ();
617 expr1 = build_compound_expr
618 (expr_tree_cons (NULL_TREE, expr1,
619 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
620 TREE_TYPE (expr1) = type;
621 result = save_expr (result);
622 return build (COND_EXPR, type, result, result, expr1);
625 /* Now back to the type we want from a void*. */
626 result = cp_convert (type, result);
627 return ifnonnull (expr, result);
632 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
633 expr, exprtype, type);
634 return error_mark_node;
638 build_dynamic_cast (type, expr)
641 if (type == error_mark_node || expr == error_mark_node)
642 return error_mark_node;
644 if (processing_template_decl)
645 return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
647 return convert_from_reference (build_dynamic_cast_1 (type, expr));
650 /* Build and initialize various sorts of descriptors. Every descriptor
651 node has a name associated with it (the name created by mangling).
652 For this reason, we use the identifier as our access to the __*_desc
653 nodes, instead of sticking them directly in the types. Otherwise we
654 would burden all built-in types (and pointer types) with slots that
655 we don't necessarily want to use.
657 For each descriptor we build, we build a variable that contains
658 the descriptor's information. When we need this info at runtime,
659 all we need is access to these variables.
661 Note: these constructors always return the address of the descriptor
662 info, since that is simplest for their mutual interaction. */
664 extern tree const_string_type_node;
666 /* Build an initializer for a __si_type_info node. */
669 expand_si_desc (tdecl, type)
674 char *name = build_overload_name (type, 1, 1);
675 tree name_string = combine_strings (build_string (strlen (name)+1, name));
677 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
678 expand_expr_stmt (get_typeid_1 (type));
679 t = decay_conversion (get_tinfo_var (type));
681 (NULL_TREE, decay_conversion (tdecl), tree_cons
682 (NULL_TREE, decay_conversion (name_string), tree_cons
683 (NULL_TREE, t, NULL_TREE)));
685 fn = get_identifier ("__rtti_si");
686 if (IDENTIFIER_GLOBAL_VALUE (fn))
687 fn = IDENTIFIER_GLOBAL_VALUE (fn);
691 push_obstacks (&permanent_obstack, &permanent_obstack);
693 (NULL_TREE, ptr_type_node, tree_cons
694 (NULL_TREE, const_string_type_node, tree_cons
695 (NULL_TREE, build_pointer_type (type_info_type_node),
697 tmp = build_function_type (void_type_node, tmp);
699 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
700 DECL_EXTERNAL (fn) = 1;
701 TREE_PUBLIC (fn) = 1;
702 DECL_ARTIFICIAL (fn) = 1;
703 pushdecl_top_level (fn);
704 make_function_rtl (fn);
705 assemble_external (fn);
709 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
710 expand_expr_stmt (fn);
713 /* Build an initializer for a __class_type_info node. */
716 expand_class_desc (tdecl, type)
724 int i = CLASSTYPE_N_BASECLASSES (type);
726 tree binfos = TYPE_BINFO_BASETYPES (type);
728 /* See code below that used these. */
729 tree vb = CLASSTYPE_VBASECLASSES (type);
732 tree base, elems, access, offset, isvir;
733 tree elt, elts = NULL_TREE;
734 static tree base_info_type_node;
736 if (base_info_type_node == NULL_TREE)
740 /* A reasonably close approximation of __class_type_info::base_info */
742 push_obstacks (&permanent_obstack, &permanent_obstack);
743 base_info_type_node = make_lang_type (RECORD_TYPE);
745 /* Actually const __user_type_info * */
746 fields [0] = build_lang_field_decl
747 (FIELD_DECL, NULL_TREE,
748 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
749 fields [1] = build_lang_field_decl
750 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
751 DECL_BIT_FIELD (fields[1]) = 1;
752 DECL_FIELD_SIZE (fields[1]) = 29;
754 fields [2] = build_lang_field_decl
755 (FIELD_DECL, NULL_TREE, boolean_type_node);
756 DECL_BIT_FIELD (fields[2]) = 1;
757 DECL_FIELD_SIZE (fields[2]) = 1;
759 /* Actually enum access */
760 fields [3] = build_lang_field_decl
761 (FIELD_DECL, NULL_TREE, integer_type_node);
762 DECL_BIT_FIELD (fields[3]) = 1;
763 DECL_FIELD_SIZE (fields[3]) = 2;
765 finish_builtin_type (base_info_type_node, "__base_info", fields,
772 tree binfo = TREE_VEC_ELT (binfos, i);
774 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
775 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
777 if (TREE_VIA_VIRTUAL (binfo))
779 tree t = BINFO_TYPE (binfo);
783 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
784 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
785 field = lookup_field (type, get_identifier (name), 0, 0);
786 offset = size_binop (FLOOR_DIV_EXPR,
787 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
788 offset = convert (sizetype, offset);
791 offset = BINFO_OFFSET (binfo);
793 if (TREE_VIA_PUBLIC (binfo))
794 access = access_public_node;
795 else if (TREE_VIA_PROTECTED (binfo))
796 access = access_protected_node;
798 access = access_private_node;
799 if (TREE_VIA_VIRTUAL (binfo))
800 isvir = boolean_true_node;
802 isvir = boolean_false_node;
805 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
806 (NULL_TREE, base, tree_cons
807 (NULL_TREE, offset, tree_cons
808 (NULL_TREE, isvir, tree_cons
809 (NULL_TREE, access, NULL_TREE)))));
810 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
811 elts = expr_tree_cons (NULL_TREE, elt, elts);
819 access = access_public_node;
822 b = TREE_VEC_ELT (binfos, i);
823 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
825 if (TREE_VIA_PUBLIC (b))
826 access = access_public_node;
827 else if (TREE_VIA_PROTECTED (b))
828 access = access_protected_node;
830 access = access_private_node;
834 base = build_t_desc (BINFO_TYPE (vb), 1);
835 offset = BINFO_OFFSET (vb);
836 isvir = build_int_2 (1, 0);
838 base_list = expr_tree_cons (NULL_TREE, base, base_list);
839 isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
840 acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
841 off_list = expr_tree_cons (NULL_TREE, offset, off_list);
844 vb = TREE_CHAIN (vb);
848 name = build_overload_name (type, 1, 1);
849 name_string = combine_strings (build_string (strlen (name)+1, name));
852 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
853 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
854 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
855 = TREE_STATIC (elts) = 1;
856 complete_array_type (arrtype, elts, 1);
860 (NULL_TREE, decay_conversion (tdecl), tree_cons
861 (NULL_TREE, decay_conversion (name_string), tree_cons
862 (NULL_TREE, decay_conversion (elts), tree_cons
863 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
866 fn = get_identifier ("__rtti_class");
867 if (IDENTIFIER_GLOBAL_VALUE (fn))
868 fn = IDENTIFIER_GLOBAL_VALUE (fn);
871 push_obstacks (&permanent_obstack, &permanent_obstack);
873 (NULL_TREE, ptr_type_node, tree_cons
874 (NULL_TREE, const_string_type_node, tree_cons
875 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
876 (NULL_TREE, sizetype, void_list_node))));
877 tmp = build_function_type (void_type_node, tmp);
879 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
880 DECL_EXTERNAL (fn) = 1;
881 TREE_PUBLIC (fn) = 1;
882 DECL_ARTIFICIAL (fn) = 1;
883 pushdecl_top_level (fn);
884 make_function_rtl (fn);
885 assemble_external (fn);
889 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
890 expand_expr_stmt (fn);
893 /* Build an initializer for a __pointer_type_info node. */
896 expand_ptr_desc (tdecl, type)
901 char *name = build_overload_name (type, 1, 1);
902 tree name_string = combine_strings (build_string (strlen (name)+1, name));
904 type = TREE_TYPE (type);
905 expand_expr_stmt (get_typeid_1 (type));
906 t = decay_conversion (get_tinfo_var (type));
908 (NULL_TREE, decay_conversion (tdecl), tree_cons
909 (NULL_TREE, decay_conversion (name_string), tree_cons
910 (NULL_TREE, t, NULL_TREE)));
912 fn = get_identifier ("__rtti_ptr");
913 if (IDENTIFIER_GLOBAL_VALUE (fn))
914 fn = IDENTIFIER_GLOBAL_VALUE (fn);
918 push_obstacks (&permanent_obstack, &permanent_obstack);
920 (NULL_TREE, ptr_type_node, tree_cons
921 (NULL_TREE, const_string_type_node, tree_cons
922 (NULL_TREE, build_pointer_type (type_info_type_node),
924 tmp = build_function_type (void_type_node, tmp);
926 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
927 DECL_EXTERNAL (fn) = 1;
928 TREE_PUBLIC (fn) = 1;
929 DECL_ARTIFICIAL (fn) = 1;
930 pushdecl_top_level (fn);
931 make_function_rtl (fn);
932 assemble_external (fn);
936 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
937 expand_expr_stmt (fn);
940 /* Build an initializer for a __attr_type_info node. */
943 expand_attr_desc (tdecl, type)
948 char *name = build_overload_name (type, 1, 1);
949 tree name_string = combine_strings (build_string (strlen (name)+1, name));
950 tree attrval = build_int_2
951 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
953 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
954 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
956 (NULL_TREE, decay_conversion (tdecl), tree_cons
957 (NULL_TREE, decay_conversion (name_string), tree_cons
958 (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
960 fn = get_identifier ("__rtti_attr");
961 if (IDENTIFIER_GLOBAL_VALUE (fn))
962 fn = IDENTIFIER_GLOBAL_VALUE (fn);
966 push_obstacks (&permanent_obstack, &permanent_obstack);
968 (NULL_TREE, ptr_type_node, tree_cons
969 (NULL_TREE, const_string_type_node, tree_cons
970 (NULL_TREE, integer_type_node, tree_cons
971 (NULL_TREE, build_pointer_type (type_info_type_node),
973 tmp = build_function_type (void_type_node, tmp);
975 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
976 DECL_EXTERNAL (fn) = 1;
977 TREE_PUBLIC (fn) = 1;
978 DECL_ARTIFICIAL (fn) = 1;
979 pushdecl_top_level (fn);
980 make_function_rtl (fn);
981 assemble_external (fn);
985 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
986 expand_expr_stmt (fn);
989 /* Build an initializer for a type_info node that just has a name. */
992 expand_generic_desc (tdecl, type, fnname)
997 char *name = build_overload_name (type, 1, 1);
998 tree name_string = combine_strings (build_string (strlen (name)+1, name));
999 tree elems = tree_cons
1000 (NULL_TREE, decay_conversion (tdecl), tree_cons
1001 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1003 tree fn = get_identifier (fnname);
1004 if (IDENTIFIER_GLOBAL_VALUE (fn))
1005 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1009 push_obstacks (&permanent_obstack, &permanent_obstack);
1011 (NULL_TREE, ptr_type_node, tree_cons
1012 (NULL_TREE, const_string_type_node, void_list_node));
1013 tmp = build_function_type (void_type_node, tmp);
1015 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1016 DECL_EXTERNAL (fn) = 1;
1017 TREE_PUBLIC (fn) = 1;
1018 DECL_ARTIFICIAL (fn) = 1;
1019 pushdecl_top_level (fn);
1020 make_function_rtl (fn);
1021 assemble_external (fn);
1025 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1026 expand_expr_stmt (fn);
1029 /* Generate the code for a type_info initialization function.
1030 Note that we take advantage of the passage
1032 5.2.7 Type identification [expr.typeid]
1034 Whether or not the destructor is called for the type_info object at the
1035 end of the program is unspecified.
1037 and don't bother to arrange for these objects to be destroyed. It
1038 doesn't matter, anyway, since the destructors don't do anything.
1040 This must only be called from toplevel (i.e. from finish_file)! */
1043 synthesize_tinfo_fn (fndecl)
1046 tree type = TREE_TYPE (DECL_NAME (fndecl));
1049 tree tdecl = get_tinfo_var (type);
1050 DECL_EXTERNAL (tdecl) = 0;
1051 TREE_STATIC (tdecl) = 1;
1052 DECL_COMMON (tdecl) = 1;
1053 TREE_USED (tdecl) = 1;
1054 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1055 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1057 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1058 store_parm_decls ();
1062 /* If the first word of the array (the vtable) is non-zero, we've already
1063 initialized the object, so don't do it again. */
1064 addr = decay_conversion (tdecl);
1065 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1066 tmp = build_indirect_ref (tmp, 0);
1067 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1068 expand_start_cond (tmp, 0);
1070 if (TREE_CODE (type) == FUNCTION_TYPE)
1071 expand_generic_desc (tdecl, type, "__rtti_func");
1072 else if (TREE_CODE (type) == ARRAY_TYPE)
1073 expand_generic_desc (tdecl, type, "__rtti_array");
1074 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1075 expand_attr_desc (tdecl, type);
1076 else if (TREE_CODE (type) == POINTER_TYPE)
1078 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1079 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1080 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1081 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1083 expand_ptr_desc (tdecl, type);
1085 else if (TYPE_PTRMEMFUNC_P (type))
1086 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1087 else if (IS_AGGR_TYPE (type))
1089 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1090 expand_generic_desc (tdecl, type, "__rtti_user");
1091 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1093 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1094 expand_si_desc (tdecl, type);
1096 expand_class_desc (tdecl, type);
1098 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1099 expand_generic_desc (tdecl, type, "__rtti_user");
1101 my_friendly_abort (252);
1105 /* OK, now return the type_info object. */
1106 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1107 tmp = build_indirect_ref (tmp, 0);
1108 c_expand_return (tmp);
1109 finish_function (lineno, 0, 0);
1113 /* This is the old dossier type descriptor generation code, it's much
1114 more extended than rtti. It's reserved for later use. */
1115 /* Build an initializer for a __t_desc node. So that we can take advantage
1116 of recursion, we accept NULL for TYPE.
1117 DEFINITION is greater than zero iff we must define the type descriptor
1118 (as opposed to merely referencing it). 1 means treat according to
1119 #pragma interface/#pragma implementation rules. 2 means define as
1120 global and public, no matter what. */
1123 build_t_desc (type, definition)
1128 tree tname, name_string;
1130 tree parents, vbases, offsets, ivars, methods, target_type;
1131 int method_count = 0, field_count = 0;
1133 if (type == NULL_TREE)
1136 tname = build_t_desc_overload (type);
1137 if (IDENTIFIER_AS_DESC (tname)
1138 && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))))
1139 return IDENTIFIER_AS_DESC (tname);
1141 tdecl = lookup_name (tname, 0);
1142 if (tdecl == NULL_TREE)
1144 tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
1145 DECL_EXTERNAL (tdecl) = 1;
1146 TREE_PUBLIC (tdecl) = 1;
1147 tdecl = pushdecl_top_level (tdecl);
1149 /* If we previously defined it, return the defined result. */
1150 else if (definition && DECL_INITIAL (tdecl))
1151 return IDENTIFIER_AS_DESC (tname);
1156 /* Let T* and T& be written only when T is written (if T is an aggr).
1157 We do this for const, but not for volatile, since volatile
1158 is rare and const is not. */
1159 if (!TYPE_VOLATILE (taggr)
1160 && (TREE_CODE (taggr) == POINTER_TYPE
1161 || TREE_CODE (taggr) == REFERENCE_TYPE)
1162 && IS_AGGR_TYPE (TREE_TYPE (taggr)))
1163 taggr = TREE_TYPE (taggr);
1165 /* If we know that we don't need to write out this type's
1166 vtable, then don't write out it's dossier. Somebody
1167 else will take care of that. */
1168 if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
1170 if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr))
1172 TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr)
1173 && CLASSTYPE_INTERFACE_KNOWN (taggr);
1174 DECL_EXTERNAL (tdecl) = 0;
1178 if (write_virtuals != 0)
1179 TREE_PUBLIC (tdecl) = 1;
1184 DECL_EXTERNAL (tdecl) = 0;
1185 TREE_PUBLIC (tdecl) = (definition > 1);
1188 SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
1190 if (!definition || DECL_EXTERNAL (tdecl))
1193 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1194 return IDENTIFIER_AS_DESC (tname);
1197 /* Show that we are defining the t_desc for this type. */
1198 DECL_INITIAL (tdecl) = error_mark_node;
1200 parents = build_expr_list (NULL_TREE, integer_zero_node);
1201 vbases = build_expr_list (NULL_TREE, integer_zero_node);
1202 offsets = build_expr_list (NULL_TREE, integer_zero_node);
1203 methods = NULL_TREE;
1206 if (TYPE_LANG_SPECIFIC (type))
1208 int i = CLASSTYPE_N_BASECLASSES (type);
1209 tree method_vec = CLASSTYPE_METHOD_VEC (type);
1211 tree binfos = TYPE_BINFO_BASETYPES (type);
1212 tree vb = CLASSTYPE_VBASECLASSES (type);
1215 parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents);
1219 vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases);
1220 offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets);
1221 vb = TREE_CHAIN (vb);
1225 for (meth = TREE_VEC_END (method_vec),
1226 end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; )
1229 methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods);
1234 if (IS_AGGR_TYPE (type))
1236 for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
1237 if (TREE_CODE (fields) == FIELD_DECL
1238 || TREE_CODE (fields) == VAR_DECL)
1240 ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars);
1243 ivars = nreverse (ivars);
1246 parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0);
1247 vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0);
1248 offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0);
1249 if (methods == NULL_TREE)
1250 methods = null_pointer_node;
1252 methods = build_unary_op (ADDR_EXPR,
1253 finish_table (NULL_TREE, __m_desc_type_node, methods, 0),
1255 if (ivars == NULL_TREE)
1256 ivars = null_pointer_node;
1258 ivars = build_unary_op (ADDR_EXPR,
1259 finish_table (NULL_TREE, __i_desc_type_node, ivars, 0),
1261 if (TREE_TYPE (type))
1262 target_type = build_t_desc (TREE_TYPE (type), definition);
1264 target_type = integer_zero_node;
1266 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
1268 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1269 tree_cons (NULL_TREE,
1270 TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node,
1271 /* really should use bitfield initialization here. */
1272 tree_cons (NULL_TREE, integer_zero_node,
1273 tree_cons (NULL_TREE, target_type,
1274 tree_cons (NULL_TREE, build_int_2 (field_count, 2),
1275 tree_cons (NULL_TREE, build_int_2 (method_count, 2),
1276 tree_cons (NULL_TREE, ivars,
1277 tree_cons (NULL_TREE, methods,
1278 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0),
1279 tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0),
1280 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0))))))))))));
1281 return build_generic_desc (tdecl, elems);
1284 /* Build an initializer for a __i_desc node. */
1290 tree elems, name_string;
1293 name_string = DECL_NAME (decl);
1294 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1296 /* Now decide whether this ivar should cause it's type to get
1297 def'd or ref'd in this file. If the type we are looking at
1298 has a proxy definition, we look at the proxy (i.e., a
1299 `foo *' is equivalent to a `foo'). */
1300 taggr = TREE_TYPE (decl);
1302 if ((TREE_CODE (taggr) == POINTER_TYPE
1303 || TREE_CODE (taggr) == REFERENCE_TYPE)
1304 && TYPE_VOLATILE (taggr) == 0)
1305 taggr = TREE_TYPE (taggr);
1307 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1308 tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl),
1309 build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl),
1310 ! IS_AGGR_TYPE (taggr)))));
1311 taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems);
1312 TREE_CONSTANT (taggr) = 1;
1313 TREE_STATIC (taggr) = 1;
1314 TREE_READONLY (taggr) = 1;
1318 /* Build an initializer for a __m_desc node. */
1324 tree taggr, elems, name_string;
1325 tree parm_count, req_count, vindex, vcontext;
1327 int p_count, r_count;
1328 tree parm_types = NULL_TREE;
1330 for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0;
1331 parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++)
1333 taggr = TREE_VALUE (parms);
1334 if ((TREE_CODE (taggr) == POINTER_TYPE
1335 || TREE_CODE (taggr) == REFERENCE_TYPE)
1336 && TYPE_VOLATILE (taggr) == 0)
1337 taggr = TREE_TYPE (taggr);
1339 parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms),
1340 ! IS_AGGR_TYPE (taggr)),
1342 if (TREE_PURPOSE (parms) == NULL_TREE)
1346 parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node),
1347 nreverse (parm_types), 0);
1348 parm_count = build_int_2 (p_count, 0);
1349 req_count = build_int_2 (r_count, 0);
1351 if (DECL_VINDEX (decl))
1352 vindex = DECL_VINDEX (decl);
1354 vindex = integer_zero_node;
1355 if (DECL_CONTEXT (decl)
1356 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
1357 vcontext = build_t_desc (DECL_CONTEXT (decl), 0);
1359 vcontext = integer_zero_node;
1360 name_string = DECL_NAME (decl);
1361 if (name_string == NULL)
1362 name_string = DECL_ASSEMBLER_NAME (decl);
1363 name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string)));
1365 /* Now decide whether the return type of this mvar
1366 should cause it's type to get def'd or ref'd in this file.
1367 If the type we are looking at has a proxy definition,
1368 we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */
1369 taggr = TREE_TYPE (TREE_TYPE (decl));
1371 if ((TREE_CODE (taggr) == POINTER_TYPE
1372 || TREE_CODE (taggr) == REFERENCE_TYPE)
1373 && TYPE_VOLATILE (taggr) == 0)
1374 taggr = TREE_TYPE (taggr);
1376 elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0),
1377 tree_cons (NULL_TREE, vindex,
1378 tree_cons (NULL_TREE, vcontext,
1379 tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)),
1380 ! IS_AGGR_TYPE (taggr)),
1381 tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)),
1382 tree_cons (NULL_TREE, parm_count,
1383 tree_cons (NULL_TREE, req_count,
1384 build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0)))))))));
1386 taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems);
1387 TREE_CONSTANT (taggr) = 1;
1388 TREE_STATIC (taggr) = 1;
1389 TREE_READONLY (taggr) = 1;
1392 #endif /* dossier */