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. */
33 #define INT_TYPE_SIZE BITS_PER_WORD
36 extern struct obstack permanent_obstack;
38 static tree call_void_fn PROTO((char *));
39 static tree build_headof_sub PROTO((tree));
40 static tree build_headof PROTO((tree));
41 static tree get_tinfo_var PROTO((tree));
42 static tree get_typeid_1 PROTO((tree));
43 static tree ifnonnull PROTO((tree, tree));
44 static tree build_dynamic_cast_1 PROTO((tree, tree));
45 static void expand_si_desc PROTO((tree, tree));
46 static void expand_class_desc PROTO((tree, tree));
47 static void expand_attr_desc PROTO((tree, tree));
48 static void expand_ptr_desc PROTO((tree, tree));
49 static void expand_generic_desc PROTO((tree, tree, char *));
50 static tree throw_bad_cast PROTO((void));
51 static tree throw_bad_typeid PROTO((void));
53 tree type_info_type_node;
58 init_rtti_processing ()
61 push_namespace (get_identifier ("std"));
62 type_info_type_node = xref_tag
63 (class_type_node, get_identifier ("type_info"), 1);
66 tinfo_fn_id = get_identifier ("__tf");
67 tinfo_fn_type = build_function_type
68 (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
72 /* Given a pointer to an object with at least one virtual table
73 pointer somewhere, return a pointer to a possible sub-object that
74 has a virtual table pointer in it that is the vtable parent for
78 build_headof_sub (exp)
81 tree type = TREE_TYPE (TREE_TYPE (exp));
82 tree basetype = CLASSTYPE_RTTI (type);
83 tree binfo = get_binfo (basetype, type, 0);
85 exp = convert_pointer_to_real (binfo, exp);
89 /* Given the expression EXP of type `class *', return the head of the
90 object pointed to by EXP with type cv void*, if the class has any
91 virtual functions (TYPE_VIRTUAL_P), else just return the
98 tree type = TREE_TYPE (exp);
102 if (TREE_CODE (type) != POINTER_TYPE)
104 error ("`headof' applied to non-pointer type");
105 return error_mark_node;
107 type = TREE_TYPE (type);
109 if (!TYPE_VIRTUAL_P (type))
112 /* If we don't have rtti stuff, get to a sub-object that does. */
113 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
114 exp = build_headof_sub (exp);
116 /* We use this a couple of times below, protect it. */
117 exp = save_expr (exp);
119 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
121 if (flag_vtable_thunks)
124 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
126 type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
127 TREE_THIS_VOLATILE (exp));
128 return build (PLUS_EXPR, type, exp,
129 cp_convert (ptrdiff_type_node, offset));
132 /* Build a call to a generic entry point taking and returning void. */
138 tree d = get_identifier (name);
141 if (IDENTIFIER_GLOBAL_VALUE (d))
142 d = IDENTIFIER_GLOBAL_VALUE (d);
145 push_obstacks (&permanent_obstack, &permanent_obstack);
147 type = build_function_type (void_type_node, void_list_node);
148 d = build_lang_decl (FUNCTION_DECL, d, type);
149 DECL_EXTERNAL (d) = 1;
151 DECL_ARTIFICIAL (d) = 1;
152 pushdecl_top_level (d);
153 make_function_rtl (d);
154 assemble_external (d);
159 return build_call (d, void_type_node, NULL_TREE);
162 /* Get a bad_cast node for the program to throw...
164 See libstdc++/exception.cc for __throw_bad_cast */
169 return call_void_fn ("__throw_bad_cast");
175 return call_void_fn ("__throw_bad_typeid");
178 /* Return the type_info function associated with the expression EXP. If
179 EXP is a reference to a polymorphic class, return the dynamic type;
180 otherwise return the static type of the expression. */
183 get_tinfo_fn_dynamic (exp)
188 if (exp == error_mark_node)
189 return error_mark_node;
191 if (type_unknown_p (exp))
193 error ("typeid of overloaded function");
194 return error_mark_node;
197 type = TREE_TYPE (exp);
199 /* peel back references, so they match. */
200 if (TREE_CODE (type) == REFERENCE_TYPE)
201 type = TREE_TYPE (type);
203 /* Peel off cv qualifiers. */
204 type = TYPE_MAIN_VARIANT (type);
206 /* If exp is a reference to polymorphic type, get the real type_info. */
207 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
209 /* build reference to type_info from vtable. */
214 warning ("taking dynamic typeid of object without -frtti");
215 push_obstacks (&permanent_obstack, &permanent_obstack);
216 init_rtti_processing ();
221 /* If we don't have rtti stuff, get to a sub-object that does. */
222 if (! CLASSTYPE_VFIELDS (type))
224 exp = build_unary_op (ADDR_EXPR, exp, 0);
225 exp = build_headof_sub (exp);
226 exp = build_indirect_ref (exp, NULL_PTR);
229 if (flag_vtable_thunks)
230 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
232 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
233 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
237 /* otherwise return the type_info for the static type of the expr. */
238 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
245 exp = get_tinfo_fn_dynamic (exp);
246 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
247 return convert_from_reference (exp);
254 tree cond = NULL_TREE;
255 tree type = TREE_TYPE (tinfo_fn_type);
258 if (processing_template_decl)
259 return build_min_nt (TYPEID_EXPR, exp);
261 if (TREE_CODE (exp) == INDIRECT_REF
262 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
263 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
264 && ! resolves_to_fixed_type_p (exp, &nonnull)
267 exp = stabilize_reference (exp);
268 cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
271 exp = get_tinfo_fn_dynamic (exp);
273 if (exp == error_mark_node)
274 return error_mark_node;
276 exp = build_call (exp, type, NULL_TREE);
280 tree bad = throw_bad_typeid ();
282 bad = build_compound_expr
283 (expr_tree_cons (NULL_TREE, bad, build_expr_list
284 (NULL_TREE, cp_convert (type, integer_zero_node))));
285 exp = build (COND_EXPR, type, cond, exp, bad);
288 return convert_from_reference (exp);
295 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
299 if (IDENTIFIER_GLOBAL_VALUE (tname))
300 return IDENTIFIER_GLOBAL_VALUE (tname);
302 /* Figure out how much space we need to allocate for the type_info object.
303 If our struct layout or the type_info classes are changed, this will
304 need to be modified. */
305 if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
306 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
307 else if (TREE_CODE (type) == POINTER_TYPE
308 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
309 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
310 size = 3 * POINTER_SIZE;
311 else if (IS_AGGR_TYPE (type))
313 if (CLASSTYPE_N_BASECLASSES (type) == 0)
314 size = 2 * POINTER_SIZE;
315 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
317 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
318 size = 3 * POINTER_SIZE;
320 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
323 size = 2 * POINTER_SIZE;
325 push_obstacks (&permanent_obstack, &permanent_obstack);
327 /* The type for a character array of the appropriate size. */
328 arrtype = build_cplus_array_type
329 (unsigned_char_type_node,
330 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
332 tdecl = build_decl (VAR_DECL, tname, arrtype);
333 TREE_PUBLIC (tdecl) = 1;
334 DECL_EXTERNAL (tdecl) = 1;
335 DECL_ARTIFICIAL (tdecl) = 1;
336 pushdecl_top_level (tdecl);
337 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
351 if (TREE_CODE (type) == OFFSET_TYPE)
352 type = TREE_TYPE (type);
353 if (TREE_CODE (type) == METHOD_TYPE)
354 type = build_function_type (TREE_TYPE (type),
355 TREE_CHAIN (TYPE_ARG_TYPES (type)));
357 name = build_overload_with_type (tinfo_fn_id, type);
359 if (IDENTIFIER_GLOBAL_VALUE (name))
360 return IDENTIFIER_GLOBAL_VALUE (name);
362 push_obstacks (&permanent_obstack, &permanent_obstack);
364 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
365 DECL_EXTERNAL (d) = 1;
367 DECL_ARTIFICIAL (d) = 1;
368 DECL_NOT_REALLY_EXTERN (d) = 1;
369 DECL_MUTABLE_P (d) = 1;
370 TREE_TYPE (name) = copy_to_permanent (type);
372 pushdecl_top_level (d);
373 make_function_rtl (d);
374 assemble_external (d);
375 mark_inline_for_output (d);
377 import_export_decl (d);
389 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
390 return convert_from_reference (t);
393 /* Return the type_info object for TYPE, creating it if necessary. */
399 if (type == error_mark_node)
400 return error_mark_node;
404 warning ("requesting typeid of object without -frtti");
405 push_obstacks (&permanent_obstack, &permanent_obstack);
406 init_rtti_processing ();
411 if (processing_template_decl)
412 return build_min_nt (TYPEID_EXPR, type);
414 /* If the type of the type-id is a reference type, the result of the
415 typeid expression refers to a type_info object representing the
417 if (TREE_CODE (type) == REFERENCE_TYPE)
418 type = TREE_TYPE (type);
420 /* The top-level cv-qualifiers of the lvalue expression or the type-id
421 that is the operand of typeid are always ignored. */
422 type = TYPE_MAIN_VARIANT (type);
424 return get_typeid_1 (type);
427 /* Check whether TEST is null before returning RESULT. If TEST is used in
428 RESULT, it must have previously had a save_expr applied to it. */
431 ifnonnull (test, result)
434 return build (COND_EXPR, TREE_TYPE (result),
435 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
436 cp_convert (TREE_TYPE (result), integer_zero_node),
440 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
444 build_dynamic_cast_1 (type, expr)
447 enum tree_code tc = TREE_CODE (type);
448 tree exprtype = TREE_TYPE (expr);
452 assert (exprtype != NULL_TREE);
453 ec = TREE_CODE (exprtype);
458 if (ec == REFERENCE_TYPE)
460 expr = convert_from_reference (expr);
461 exprtype = TREE_TYPE (expr);
462 ec = TREE_CODE (exprtype);
464 if (ec != POINTER_TYPE)
466 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
468 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
470 if (TREE_READONLY (TREE_TYPE (exprtype))
471 && ! TYPE_READONLY (TREE_TYPE (type)))
473 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
475 /* else fall through */
477 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
479 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
482 /* else fall through */
487 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
488 if (ec == RECORD_TYPE)
490 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
491 TREE_THIS_VOLATILE (expr));
492 exprtype = build_reference_type (exprtype);
493 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
494 LOOKUP_NORMAL, NULL_TREE);
498 if (tc == REFERENCE_TYPE)
500 if (ec != REFERENCE_TYPE)
502 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
504 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
506 if (TREE_READONLY (TREE_TYPE (exprtype))
507 && ! TYPE_READONLY (TREE_TYPE (type)))
511 /* If *type is an unambiguous accessible base class of *exprtype,
512 convert statically. */
517 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
520 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
523 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
524 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
527 /* if TYPE is `void *', return pointer to complete object. */
528 if (tc == POINTER_TYPE
529 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
531 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
532 if (TREE_CODE (expr) == ADDR_EXPR
533 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
534 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
535 return build1 (NOP_EXPR, type, expr);
537 /* Since expr is used twice below, save it. */
538 expr = save_expr (expr);
540 expr1 = build_headof (expr);
541 if (TREE_TYPE (expr1) != type)
542 expr1 = build1 (NOP_EXPR, type, expr1);
543 return ifnonnull (expr, expr1);
548 tree result, td1, td2, td3, elems, expr2;
550 /* If we got here, we can't convert statically. Therefore,
551 dynamic_cast<D&>(b) (b an object) cannot succeed. */
552 if (ec == REFERENCE_TYPE)
554 if (TREE_CODE (expr) == VAR_DECL
555 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
557 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
559 return throw_bad_cast ();
562 /* Ditto for dynamic_cast<D*>(&b). */
563 else if (TREE_CODE (expr) == ADDR_EXPR)
565 tree op = TREE_OPERAND (expr, 0);
566 if (TREE_CODE (op) == VAR_DECL
567 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
569 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
571 retval = build_int_2 (0, 0);
572 TREE_TYPE (retval) = type;
577 /* Since expr is used twice below, save it. */
578 expr = save_expr (expr);
581 if (tc == REFERENCE_TYPE)
582 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
584 /* Build run-time conversion. */
585 expr2 = build_headof (expr1);
587 if (ec == POINTER_TYPE)
588 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
590 td1 = get_tinfo_fn_dynamic (expr);
591 td1 = decay_conversion (td1);
593 td2 = decay_conversion
594 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
595 td3 = decay_conversion
596 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
599 (NULL_TREE, td1, tree_cons
600 (NULL_TREE, td2, tree_cons
601 (NULL_TREE, build_int_2 (1, 0), tree_cons
602 (NULL_TREE, expr2, tree_cons
603 (NULL_TREE, td3, tree_cons
604 (NULL_TREE, expr1, NULL_TREE))))));
606 dcast_fn = get_identifier ("__dynamic_cast");
607 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
608 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
613 push_obstacks (&permanent_obstack, &permanent_obstack);
615 (NULL_TREE, TREE_TYPE (td1), tree_cons
616 (NULL_TREE, TREE_TYPE (td1), tree_cons
617 (NULL_TREE, integer_type_node, tree_cons
618 (NULL_TREE, ptr_type_node, tree_cons
619 (NULL_TREE, TREE_TYPE (td1), tree_cons
620 (NULL_TREE, ptr_type_node, void_list_node))))));
621 tmp = build_function_type (ptr_type_node, tmp);
622 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
623 DECL_EXTERNAL (dcast_fn) = 1;
624 TREE_PUBLIC (dcast_fn) = 1;
625 DECL_ARTIFICIAL (dcast_fn) = 1;
626 pushdecl_top_level (dcast_fn);
627 make_function_rtl (dcast_fn);
628 assemble_external (dcast_fn);
633 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
635 if (tc == REFERENCE_TYPE)
637 expr1 = throw_bad_cast ();
638 expr1 = build_compound_expr
639 (expr_tree_cons (NULL_TREE, expr1,
640 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
641 TREE_TYPE (expr1) = type;
642 result = save_expr (result);
643 return build (COND_EXPR, type, result, result, expr1);
646 /* Now back to the type we want from a void*. */
647 result = cp_convert (type, result);
648 return ifnonnull (expr, result);
653 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
654 expr, exprtype, type);
655 return error_mark_node;
659 build_dynamic_cast (type, expr)
662 if (type == error_mark_node || expr == error_mark_node)
663 return error_mark_node;
665 if (processing_template_decl)
666 return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
668 return convert_from_reference (build_dynamic_cast_1 (type, expr));
671 /* Build and initialize various sorts of descriptors. Every descriptor
672 node has a name associated with it (the name created by mangling).
673 For this reason, we use the identifier as our access to the __*_desc
674 nodes, instead of sticking them directly in the types. Otherwise we
675 would burden all built-in types (and pointer types) with slots that
676 we don't necessarily want to use.
678 For each descriptor we build, we build a variable that contains
679 the descriptor's information. When we need this info at runtime,
680 all we need is access to these variables.
682 Note: these constructors always return the address of the descriptor
683 info, since that is simplest for their mutual interaction. */
685 extern tree const_string_type_node;
687 /* Build an initializer for a __si_type_info node. */
690 expand_si_desc (tdecl, type)
695 char *name = build_overload_name (type, 1, 1);
696 tree name_string = combine_strings (build_string (strlen (name)+1, name));
698 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
699 expand_expr_stmt (get_typeid_1 (type));
700 t = decay_conversion (get_tinfo_var (type));
702 (NULL_TREE, decay_conversion (tdecl), tree_cons
703 (NULL_TREE, decay_conversion (name_string), tree_cons
704 (NULL_TREE, t, NULL_TREE)));
706 fn = get_identifier ("__rtti_si");
707 if (IDENTIFIER_GLOBAL_VALUE (fn))
708 fn = IDENTIFIER_GLOBAL_VALUE (fn);
712 push_obstacks (&permanent_obstack, &permanent_obstack);
714 (NULL_TREE, ptr_type_node, tree_cons
715 (NULL_TREE, const_string_type_node, tree_cons
716 (NULL_TREE, build_pointer_type (type_info_type_node),
718 tmp = build_function_type (void_type_node, tmp);
720 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
721 DECL_EXTERNAL (fn) = 1;
722 TREE_PUBLIC (fn) = 1;
723 DECL_ARTIFICIAL (fn) = 1;
724 pushdecl_top_level (fn);
725 make_function_rtl (fn);
726 assemble_external (fn);
730 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
731 expand_expr_stmt (fn);
734 /* Build an initializer for a __class_type_info node. */
737 expand_class_desc (tdecl, type)
745 int i = CLASSTYPE_N_BASECLASSES (type);
747 tree binfos = TYPE_BINFO_BASETYPES (type);
749 /* See code below that used these. */
750 tree vb = CLASSTYPE_VBASECLASSES (type);
753 tree base, elems, access, offset, isvir;
754 tree elt, elts = NULL_TREE;
755 static tree base_info_type_node;
757 if (base_info_type_node == NULL_TREE)
761 /* A reasonably close approximation of __class_type_info::base_info */
763 push_obstacks (&permanent_obstack, &permanent_obstack);
764 base_info_type_node = make_lang_type (RECORD_TYPE);
766 /* Actually const __user_type_info * */
767 fields [0] = build_lang_field_decl
768 (FIELD_DECL, NULL_TREE,
769 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
770 fields [1] = build_lang_field_decl
771 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
772 DECL_BIT_FIELD (fields[1]) = 1;
773 DECL_FIELD_SIZE (fields[1]) = 29;
775 fields [2] = build_lang_field_decl
776 (FIELD_DECL, NULL_TREE, boolean_type_node);
777 DECL_BIT_FIELD (fields[2]) = 1;
778 DECL_FIELD_SIZE (fields[2]) = 1;
780 /* Actually enum access */
781 fields [3] = build_lang_field_decl
782 (FIELD_DECL, NULL_TREE, integer_type_node);
783 DECL_BIT_FIELD (fields[3]) = 1;
784 DECL_FIELD_SIZE (fields[3]) = 2;
786 finish_builtin_type (base_info_type_node, "__base_info", fields,
793 tree binfo = TREE_VEC_ELT (binfos, i);
795 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
796 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
798 if (TREE_VIA_VIRTUAL (binfo))
800 tree t = BINFO_TYPE (binfo);
804 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
805 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
806 field = lookup_field (type, get_identifier (name), 0, 0);
807 offset = size_binop (FLOOR_DIV_EXPR,
808 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
809 offset = convert (sizetype, offset);
812 offset = BINFO_OFFSET (binfo);
814 if (TREE_VIA_PUBLIC (binfo))
815 access = access_public_node;
816 else if (TREE_VIA_PROTECTED (binfo))
817 access = access_protected_node;
819 access = access_private_node;
820 if (TREE_VIA_VIRTUAL (binfo))
821 isvir = boolean_true_node;
823 isvir = boolean_false_node;
826 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
827 (NULL_TREE, base, tree_cons
828 (NULL_TREE, offset, tree_cons
829 (NULL_TREE, isvir, tree_cons
830 (NULL_TREE, access, NULL_TREE)))));
831 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
832 elts = expr_tree_cons (NULL_TREE, elt, elts);
840 access = access_public_node;
843 b = TREE_VEC_ELT (binfos, i);
844 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
846 if (TREE_VIA_PUBLIC (b))
847 access = access_public_node;
848 else if (TREE_VIA_PROTECTED (b))
849 access = access_protected_node;
851 access = access_private_node;
855 base = build_t_desc (BINFO_TYPE (vb), 1);
856 offset = BINFO_OFFSET (vb);
857 isvir = build_int_2 (1, 0);
859 base_list = expr_tree_cons (NULL_TREE, base, base_list);
860 isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
861 acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
862 off_list = expr_tree_cons (NULL_TREE, offset, off_list);
865 vb = TREE_CHAIN (vb);
869 name = build_overload_name (type, 1, 1);
870 name_string = combine_strings (build_string (strlen (name)+1, name));
873 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
874 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
875 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
876 = TREE_STATIC (elts) = 1;
877 complete_array_type (arrtype, elts, 1);
881 (NULL_TREE, decay_conversion (tdecl), tree_cons
882 (NULL_TREE, decay_conversion (name_string), tree_cons
883 (NULL_TREE, decay_conversion (elts), tree_cons
884 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
887 fn = get_identifier ("__rtti_class");
888 if (IDENTIFIER_GLOBAL_VALUE (fn))
889 fn = IDENTIFIER_GLOBAL_VALUE (fn);
892 push_obstacks (&permanent_obstack, &permanent_obstack);
894 (NULL_TREE, ptr_type_node, tree_cons
895 (NULL_TREE, const_string_type_node, tree_cons
896 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
897 (NULL_TREE, sizetype, void_list_node))));
898 tmp = build_function_type (void_type_node, tmp);
900 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
901 DECL_EXTERNAL (fn) = 1;
902 TREE_PUBLIC (fn) = 1;
903 DECL_ARTIFICIAL (fn) = 1;
904 pushdecl_top_level (fn);
905 make_function_rtl (fn);
906 assemble_external (fn);
910 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
911 expand_expr_stmt (fn);
914 /* Build an initializer for a __pointer_type_info node. */
917 expand_ptr_desc (tdecl, type)
922 char *name = build_overload_name (type, 1, 1);
923 tree name_string = combine_strings (build_string (strlen (name)+1, name));
925 type = TREE_TYPE (type);
926 expand_expr_stmt (get_typeid_1 (type));
927 t = decay_conversion (get_tinfo_var (type));
929 (NULL_TREE, decay_conversion (tdecl), tree_cons
930 (NULL_TREE, decay_conversion (name_string), tree_cons
931 (NULL_TREE, t, NULL_TREE)));
933 fn = get_identifier ("__rtti_ptr");
934 if (IDENTIFIER_GLOBAL_VALUE (fn))
935 fn = IDENTIFIER_GLOBAL_VALUE (fn);
939 push_obstacks (&permanent_obstack, &permanent_obstack);
941 (NULL_TREE, ptr_type_node, tree_cons
942 (NULL_TREE, const_string_type_node, tree_cons
943 (NULL_TREE, build_pointer_type (type_info_type_node),
945 tmp = build_function_type (void_type_node, tmp);
947 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
948 DECL_EXTERNAL (fn) = 1;
949 TREE_PUBLIC (fn) = 1;
950 DECL_ARTIFICIAL (fn) = 1;
951 pushdecl_top_level (fn);
952 make_function_rtl (fn);
953 assemble_external (fn);
957 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
958 expand_expr_stmt (fn);
961 /* Build an initializer for a __attr_type_info node. */
964 expand_attr_desc (tdecl, type)
969 char *name = build_overload_name (type, 1, 1);
970 tree name_string = combine_strings (build_string (strlen (name)+1, name));
971 tree attrval = build_int_2
972 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
974 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
975 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
977 (NULL_TREE, decay_conversion (tdecl), tree_cons
978 (NULL_TREE, decay_conversion (name_string), tree_cons
979 (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
981 fn = get_identifier ("__rtti_attr");
982 if (IDENTIFIER_GLOBAL_VALUE (fn))
983 fn = IDENTIFIER_GLOBAL_VALUE (fn);
987 push_obstacks (&permanent_obstack, &permanent_obstack);
989 (NULL_TREE, ptr_type_node, tree_cons
990 (NULL_TREE, const_string_type_node, tree_cons
991 (NULL_TREE, integer_type_node, tree_cons
992 (NULL_TREE, build_pointer_type (type_info_type_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 /* Build an initializer for a type_info node that just has a name. */
1013 expand_generic_desc (tdecl, type, fnname)
1018 char *name = build_overload_name (type, 1, 1);
1019 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1020 tree elems = tree_cons
1021 (NULL_TREE, decay_conversion (tdecl), tree_cons
1022 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1024 tree fn = get_identifier (fnname);
1025 if (IDENTIFIER_GLOBAL_VALUE (fn))
1026 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1030 push_obstacks (&permanent_obstack, &permanent_obstack);
1032 (NULL_TREE, ptr_type_node, tree_cons
1033 (NULL_TREE, const_string_type_node, void_list_node));
1034 tmp = build_function_type (void_type_node, tmp);
1036 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1037 DECL_EXTERNAL (fn) = 1;
1038 TREE_PUBLIC (fn) = 1;
1039 DECL_ARTIFICIAL (fn) = 1;
1040 pushdecl_top_level (fn);
1041 make_function_rtl (fn);
1042 assemble_external (fn);
1046 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1047 expand_expr_stmt (fn);
1050 /* Generate the code for a type_info initialization function.
1051 Note that we take advantage of the passage
1053 5.2.7 Type identification [expr.typeid]
1055 Whether or not the destructor is called for the type_info object at the
1056 end of the program is unspecified.
1058 and don't bother to arrange for these objects to be destroyed. It
1059 doesn't matter, anyway, since the destructors don't do anything.
1061 This must only be called from toplevel (i.e. from finish_file)! */
1064 synthesize_tinfo_fn (fndecl)
1067 tree type = TREE_TYPE (DECL_NAME (fndecl));
1070 tree tdecl = get_tinfo_var (type);
1071 DECL_EXTERNAL (tdecl) = 0;
1072 TREE_STATIC (tdecl) = 1;
1073 DECL_COMMON (tdecl) = 1;
1074 TREE_USED (tdecl) = 1;
1075 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1076 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1078 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1079 store_parm_decls ();
1083 /* If the first word of the array (the vtable) is non-zero, we've already
1084 initialized the object, so don't do it again. */
1085 addr = decay_conversion (tdecl);
1086 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1087 tmp = build_indirect_ref (tmp, 0);
1088 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1089 expand_start_cond (tmp, 0);
1091 if (TREE_CODE (type) == FUNCTION_TYPE)
1092 expand_generic_desc (tdecl, type, "__rtti_func");
1093 else if (TREE_CODE (type) == ARRAY_TYPE)
1094 expand_generic_desc (tdecl, type, "__rtti_array");
1095 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1096 expand_attr_desc (tdecl, type);
1097 else if (TREE_CODE (type) == POINTER_TYPE)
1099 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1100 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1101 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1102 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1104 expand_ptr_desc (tdecl, type);
1106 else if (TYPE_PTRMEMFUNC_P (type))
1107 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1108 else if (IS_AGGR_TYPE (type))
1110 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1111 expand_generic_desc (tdecl, type, "__rtti_user");
1112 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1114 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1115 expand_si_desc (tdecl, type);
1117 expand_class_desc (tdecl, type);
1119 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1120 expand_generic_desc (tdecl, type, "__rtti_user");
1122 my_friendly_abort (252);
1126 /* OK, now return the type_info object. */
1127 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1128 tmp = build_indirect_ref (tmp, 0);
1129 c_expand_return (tmp);
1130 finish_function (lineno, 0, 0);