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. */
209 warning ("taking dynamic typeid of object without -frtti");
210 push_obstacks (&permanent_obstack, &permanent_obstack);
211 init_rtti_processing ();
216 /* If we don't have rtti stuff, get to a sub-object that does. */
217 if (! CLASSTYPE_VFIELDS (type))
219 exp = build_unary_op (ADDR_EXPR, exp, 0);
220 exp = build_headof_sub (exp);
221 exp = build_indirect_ref (exp, NULL_PTR);
224 if (flag_vtable_thunks)
225 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
227 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
228 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
232 /* otherwise return the type_info for the static type of the expr. */
233 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
240 exp = get_tinfo_fn_dynamic (exp);
241 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
242 return convert_from_reference (exp);
249 tree cond = NULL_TREE;
250 tree type = TREE_TYPE (tinfo_fn_type);
253 if (processing_template_decl)
254 return build_min_nt (TYPEID_EXPR, exp);
256 if (TREE_CODE (exp) == INDIRECT_REF
257 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
258 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
259 && ! resolves_to_fixed_type_p (exp, &nonnull)
262 exp = stabilize_reference (exp);
263 cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
266 exp = get_tinfo_fn_dynamic (exp);
268 if (exp == error_mark_node)
269 return error_mark_node;
271 exp = build_call (exp, type, NULL_TREE);
275 tree bad = throw_bad_typeid ();
277 bad = build_compound_expr
278 (expr_tree_cons (NULL_TREE, bad, build_expr_list
279 (NULL_TREE, cp_convert (type, integer_zero_node))));
280 exp = build (COND_EXPR, type, cond, exp, bad);
283 return convert_from_reference (exp);
290 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
294 if (IDENTIFIER_GLOBAL_VALUE (tname))
295 return IDENTIFIER_GLOBAL_VALUE (tname);
297 /* Figure out how much space we need to allocate for the type_info object.
298 If our struct layout or the type_info classes are changed, this will
299 need to be modified. */
300 if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
301 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
302 else if (TREE_CODE (type) == POINTER_TYPE
303 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
304 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
305 size = 3 * POINTER_SIZE;
306 else if (IS_AGGR_TYPE (type))
308 if (CLASSTYPE_N_BASECLASSES (type) == 0)
309 size = 2 * POINTER_SIZE;
310 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
312 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
313 size = 3 * POINTER_SIZE;
315 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
318 size = 2 * POINTER_SIZE;
320 push_obstacks (&permanent_obstack, &permanent_obstack);
322 /* The type for a character array of the appropriate size. */
323 arrtype = build_cplus_array_type
324 (unsigned_char_type_node,
325 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
327 tdecl = build_decl (VAR_DECL, tname, arrtype);
328 TREE_PUBLIC (tdecl) = 1;
329 DECL_EXTERNAL (tdecl) = 1;
330 DECL_ARTIFICIAL (tdecl) = 1;
331 pushdecl_top_level (tdecl);
332 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
346 if (TREE_CODE (type) == OFFSET_TYPE)
347 type = TREE_TYPE (type);
348 if (TREE_CODE (type) == METHOD_TYPE)
349 type = build_function_type (TREE_TYPE (type),
350 TREE_CHAIN (TYPE_ARG_TYPES (type)));
352 name = build_overload_with_type (tinfo_fn_id, type);
354 if (IDENTIFIER_GLOBAL_VALUE (name))
355 return IDENTIFIER_GLOBAL_VALUE (name);
357 push_obstacks (&permanent_obstack, &permanent_obstack);
359 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
360 DECL_EXTERNAL (d) = 1;
362 DECL_ARTIFICIAL (d) = 1;
363 DECL_NOT_REALLY_EXTERN (d) = 1;
364 DECL_MUTABLE_P (d) = 1;
365 TREE_TYPE (name) = copy_to_permanent (type);
366 pushdecl_top_level (d);
367 make_function_rtl (d);
368 assemble_external (d);
369 mark_inline_for_output (d);
371 import_export_decl (d);
383 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
384 return convert_from_reference (t);
387 /* Return the type_info object for TYPE, creating it if necessary. */
393 if (type == error_mark_node)
394 return error_mark_node;
398 warning ("requesting typeid of object without -frtti");
399 push_obstacks (&permanent_obstack, &permanent_obstack);
400 init_rtti_processing ();
405 if (processing_template_decl)
406 return build_min_nt (TYPEID_EXPR, type);
408 /* If the type of the type-id is a reference type, the result of the
409 typeid expression refers to a type_info object representing the
411 if (TREE_CODE (type) == REFERENCE_TYPE)
412 type = TREE_TYPE (type);
414 /* The top-level cv-qualifiers of the lvalue expression or the type-id
415 that is the operand of typeid are always ignored. */
416 type = TYPE_MAIN_VARIANT (type);
418 return get_typeid_1 (type);
421 /* Check whether TEST is null before returning RESULT. If TEST is used in
422 RESULT, it must have previously had a save_expr applied to it. */
425 ifnonnull (test, result)
428 return build (COND_EXPR, TREE_TYPE (result),
429 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
430 cp_convert (TREE_TYPE (result), integer_zero_node),
434 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
438 build_dynamic_cast_1 (type, expr)
441 enum tree_code tc = TREE_CODE (type);
442 tree exprtype = TREE_TYPE (expr);
446 assert (exprtype != NULL_TREE);
447 ec = TREE_CODE (exprtype);
452 if (ec == REFERENCE_TYPE)
454 expr = convert_from_reference (expr);
455 exprtype = TREE_TYPE (expr);
456 ec = TREE_CODE (exprtype);
458 if (ec != POINTER_TYPE)
460 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
462 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
464 if (TREE_READONLY (TREE_TYPE (exprtype))
465 && ! TYPE_READONLY (TREE_TYPE (type)))
467 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
469 /* else fall through */
471 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
473 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
476 /* else fall through */
481 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
482 if (ec == RECORD_TYPE)
484 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
485 TREE_THIS_VOLATILE (expr));
486 exprtype = build_reference_type (exprtype);
487 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
488 LOOKUP_NORMAL, NULL_TREE);
492 if (tc == REFERENCE_TYPE)
494 if (ec != REFERENCE_TYPE)
496 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
498 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
500 if (TREE_READONLY (TREE_TYPE (exprtype))
501 && ! TYPE_READONLY (TREE_TYPE (type)))
505 /* If *type is an unambiguous accessible base class of *exprtype,
506 convert statically. */
511 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
514 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
517 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
518 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
521 /* if TYPE is `void *', return pointer to complete object. */
522 if (tc == POINTER_TYPE
523 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
525 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
526 if (TREE_CODE (expr) == ADDR_EXPR
527 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
528 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
529 return build1 (NOP_EXPR, type, expr);
531 /* Since expr is used twice below, save it. */
532 expr = save_expr (expr);
534 expr1 = build_headof (expr);
535 if (TREE_TYPE (expr1) != type)
536 expr1 = build1 (NOP_EXPR, type, expr1);
537 return ifnonnull (expr, expr1);
542 tree result, td1, td2, td3, elems, expr2;
544 /* If we got here, we can't convert statically. Therefore,
545 dynamic_cast<D&>(b) (b an object) cannot succeed. */
546 if (ec == REFERENCE_TYPE)
548 if (TREE_CODE (expr) == VAR_DECL
549 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
551 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
553 return throw_bad_cast ();
556 /* Ditto for dynamic_cast<D*>(&b). */
557 else if (TREE_CODE (expr) == ADDR_EXPR)
559 tree op = TREE_OPERAND (expr, 0);
560 if (TREE_CODE (op) == VAR_DECL
561 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
563 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
565 retval = build_int_2 (0, 0);
566 TREE_TYPE (retval) = type;
571 /* Since expr is used twice below, save it. */
572 expr = save_expr (expr);
575 if (tc == REFERENCE_TYPE)
576 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
578 /* Build run-time conversion. */
579 expr2 = build_headof (expr1);
581 if (ec == POINTER_TYPE)
582 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
584 td1 = get_tinfo_fn_dynamic (expr);
585 td1 = decay_conversion (td1);
587 td2 = decay_conversion
588 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
589 td3 = decay_conversion
590 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
593 (NULL_TREE, td1, tree_cons
594 (NULL_TREE, td2, tree_cons
595 (NULL_TREE, build_int_2 (1, 0), tree_cons
596 (NULL_TREE, expr2, tree_cons
597 (NULL_TREE, td3, tree_cons
598 (NULL_TREE, expr1, NULL_TREE))))));
600 dcast_fn = get_identifier ("__dynamic_cast");
601 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
602 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
607 push_obstacks (&permanent_obstack, &permanent_obstack);
609 (NULL_TREE, TREE_TYPE (td1), tree_cons
610 (NULL_TREE, TREE_TYPE (td1), tree_cons
611 (NULL_TREE, integer_type_node, tree_cons
612 (NULL_TREE, ptr_type_node, tree_cons
613 (NULL_TREE, TREE_TYPE (td1), tree_cons
614 (NULL_TREE, ptr_type_node, void_list_node))))));
615 tmp = build_function_type (ptr_type_node, tmp);
616 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
617 DECL_EXTERNAL (dcast_fn) = 1;
618 TREE_PUBLIC (dcast_fn) = 1;
619 DECL_ARTIFICIAL (dcast_fn) = 1;
620 pushdecl_top_level (dcast_fn);
621 make_function_rtl (dcast_fn);
622 assemble_external (dcast_fn);
627 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
629 if (tc == REFERENCE_TYPE)
631 expr1 = throw_bad_cast ();
632 expr1 = build_compound_expr
633 (expr_tree_cons (NULL_TREE, expr1,
634 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
635 TREE_TYPE (expr1) = type;
636 result = save_expr (result);
637 return build (COND_EXPR, type, result, result, expr1);
640 /* Now back to the type we want from a void*. */
641 result = cp_convert (type, result);
642 return ifnonnull (expr, result);
647 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
648 expr, exprtype, type);
649 return error_mark_node;
653 build_dynamic_cast (type, expr)
656 if (type == error_mark_node || expr == error_mark_node)
657 return error_mark_node;
659 if (processing_template_decl)
660 return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
662 return convert_from_reference (build_dynamic_cast_1 (type, expr));
665 /* Build and initialize various sorts of descriptors. Every descriptor
666 node has a name associated with it (the name created by mangling).
667 For this reason, we use the identifier as our access to the __*_desc
668 nodes, instead of sticking them directly in the types. Otherwise we
669 would burden all built-in types (and pointer types) with slots that
670 we don't necessarily want to use.
672 For each descriptor we build, we build a variable that contains
673 the descriptor's information. When we need this info at runtime,
674 all we need is access to these variables.
676 Note: these constructors always return the address of the descriptor
677 info, since that is simplest for their mutual interaction. */
679 extern tree const_string_type_node;
681 /* Build an initializer for a __si_type_info node. */
684 expand_si_desc (tdecl, type)
689 char *name = build_overload_name (type, 1, 1);
690 tree name_string = combine_strings (build_string (strlen (name)+1, name));
692 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
693 expand_expr_stmt (get_typeid_1 (type));
694 t = decay_conversion (get_tinfo_var (type));
696 (NULL_TREE, decay_conversion (tdecl), tree_cons
697 (NULL_TREE, decay_conversion (name_string), tree_cons
698 (NULL_TREE, t, NULL_TREE)));
700 fn = get_identifier ("__rtti_si");
701 if (IDENTIFIER_GLOBAL_VALUE (fn))
702 fn = IDENTIFIER_GLOBAL_VALUE (fn);
706 push_obstacks (&permanent_obstack, &permanent_obstack);
708 (NULL_TREE, ptr_type_node, tree_cons
709 (NULL_TREE, const_string_type_node, tree_cons
710 (NULL_TREE, build_pointer_type (type_info_type_node),
712 tmp = build_function_type (void_type_node, tmp);
714 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
715 DECL_EXTERNAL (fn) = 1;
716 TREE_PUBLIC (fn) = 1;
717 DECL_ARTIFICIAL (fn) = 1;
718 pushdecl_top_level (fn);
719 make_function_rtl (fn);
720 assemble_external (fn);
724 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
725 expand_expr_stmt (fn);
728 /* Build an initializer for a __class_type_info node. */
731 expand_class_desc (tdecl, type)
739 int i = CLASSTYPE_N_BASECLASSES (type);
741 tree binfos = TYPE_BINFO_BASETYPES (type);
743 /* See code below that used these. */
744 tree vb = CLASSTYPE_VBASECLASSES (type);
747 tree base, elems, access, offset, isvir;
748 tree elt, elts = NULL_TREE;
749 static tree base_info_type_node;
751 if (base_info_type_node == NULL_TREE)
755 /* A reasonably close approximation of __class_type_info::base_info */
757 push_obstacks (&permanent_obstack, &permanent_obstack);
758 base_info_type_node = make_lang_type (RECORD_TYPE);
760 /* Actually const __user_type_info * */
761 fields [0] = build_lang_field_decl
762 (FIELD_DECL, NULL_TREE,
763 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
764 fields [1] = build_lang_field_decl
765 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
766 DECL_BIT_FIELD (fields[1]) = 1;
767 DECL_FIELD_SIZE (fields[1]) = 29;
769 fields [2] = build_lang_field_decl
770 (FIELD_DECL, NULL_TREE, boolean_type_node);
771 DECL_BIT_FIELD (fields[2]) = 1;
772 DECL_FIELD_SIZE (fields[2]) = 1;
774 /* Actually enum access */
775 fields [3] = build_lang_field_decl
776 (FIELD_DECL, NULL_TREE, integer_type_node);
777 DECL_BIT_FIELD (fields[3]) = 1;
778 DECL_FIELD_SIZE (fields[3]) = 2;
780 finish_builtin_type (base_info_type_node, "__base_info", fields,
787 tree binfo = TREE_VEC_ELT (binfos, i);
789 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
790 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
792 if (TREE_VIA_VIRTUAL (binfo))
794 tree t = BINFO_TYPE (binfo);
798 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
799 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
800 field = lookup_field (type, get_identifier (name), 0, 0);
801 offset = size_binop (FLOOR_DIV_EXPR,
802 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
803 offset = convert (sizetype, offset);
806 offset = BINFO_OFFSET (binfo);
808 if (TREE_VIA_PUBLIC (binfo))
809 access = access_public_node;
810 else if (TREE_VIA_PROTECTED (binfo))
811 access = access_protected_node;
813 access = access_private_node;
814 if (TREE_VIA_VIRTUAL (binfo))
815 isvir = boolean_true_node;
817 isvir = boolean_false_node;
820 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
821 (NULL_TREE, base, tree_cons
822 (NULL_TREE, offset, tree_cons
823 (NULL_TREE, isvir, tree_cons
824 (NULL_TREE, access, NULL_TREE)))));
825 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
826 elts = expr_tree_cons (NULL_TREE, elt, elts);
834 access = access_public_node;
837 b = TREE_VEC_ELT (binfos, i);
838 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
840 if (TREE_VIA_PUBLIC (b))
841 access = access_public_node;
842 else if (TREE_VIA_PROTECTED (b))
843 access = access_protected_node;
845 access = access_private_node;
849 base = build_t_desc (BINFO_TYPE (vb), 1);
850 offset = BINFO_OFFSET (vb);
851 isvir = build_int_2 (1, 0);
853 base_list = expr_tree_cons (NULL_TREE, base, base_list);
854 isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
855 acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
856 off_list = expr_tree_cons (NULL_TREE, offset, off_list);
859 vb = TREE_CHAIN (vb);
863 name = build_overload_name (type, 1, 1);
864 name_string = combine_strings (build_string (strlen (name)+1, name));
867 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
868 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
869 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
870 = TREE_STATIC (elts) = 1;
871 complete_array_type (arrtype, elts, 1);
875 (NULL_TREE, decay_conversion (tdecl), tree_cons
876 (NULL_TREE, decay_conversion (name_string), tree_cons
877 (NULL_TREE, decay_conversion (elts), tree_cons
878 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
881 fn = get_identifier ("__rtti_class");
882 if (IDENTIFIER_GLOBAL_VALUE (fn))
883 fn = IDENTIFIER_GLOBAL_VALUE (fn);
886 push_obstacks (&permanent_obstack, &permanent_obstack);
888 (NULL_TREE, ptr_type_node, tree_cons
889 (NULL_TREE, const_string_type_node, tree_cons
890 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
891 (NULL_TREE, sizetype, void_list_node))));
892 tmp = build_function_type (void_type_node, tmp);
894 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
895 DECL_EXTERNAL (fn) = 1;
896 TREE_PUBLIC (fn) = 1;
897 DECL_ARTIFICIAL (fn) = 1;
898 pushdecl_top_level (fn);
899 make_function_rtl (fn);
900 assemble_external (fn);
904 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
905 expand_expr_stmt (fn);
908 /* Build an initializer for a __pointer_type_info node. */
911 expand_ptr_desc (tdecl, type)
916 char *name = build_overload_name (type, 1, 1);
917 tree name_string = combine_strings (build_string (strlen (name)+1, name));
919 type = TREE_TYPE (type);
920 expand_expr_stmt (get_typeid_1 (type));
921 t = decay_conversion (get_tinfo_var (type));
923 (NULL_TREE, decay_conversion (tdecl), tree_cons
924 (NULL_TREE, decay_conversion (name_string), tree_cons
925 (NULL_TREE, t, NULL_TREE)));
927 fn = get_identifier ("__rtti_ptr");
928 if (IDENTIFIER_GLOBAL_VALUE (fn))
929 fn = IDENTIFIER_GLOBAL_VALUE (fn);
933 push_obstacks (&permanent_obstack, &permanent_obstack);
935 (NULL_TREE, ptr_type_node, tree_cons
936 (NULL_TREE, const_string_type_node, tree_cons
937 (NULL_TREE, build_pointer_type (type_info_type_node),
939 tmp = build_function_type (void_type_node, tmp);
941 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
942 DECL_EXTERNAL (fn) = 1;
943 TREE_PUBLIC (fn) = 1;
944 DECL_ARTIFICIAL (fn) = 1;
945 pushdecl_top_level (fn);
946 make_function_rtl (fn);
947 assemble_external (fn);
951 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
952 expand_expr_stmt (fn);
955 /* Build an initializer for a __attr_type_info node. */
958 expand_attr_desc (tdecl, type)
963 char *name = build_overload_name (type, 1, 1);
964 tree name_string = combine_strings (build_string (strlen (name)+1, name));
965 tree attrval = build_int_2
966 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
968 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
969 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
971 (NULL_TREE, decay_conversion (tdecl), tree_cons
972 (NULL_TREE, decay_conversion (name_string), tree_cons
973 (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
975 fn = get_identifier ("__rtti_attr");
976 if (IDENTIFIER_GLOBAL_VALUE (fn))
977 fn = IDENTIFIER_GLOBAL_VALUE (fn);
981 push_obstacks (&permanent_obstack, &permanent_obstack);
983 (NULL_TREE, ptr_type_node, tree_cons
984 (NULL_TREE, const_string_type_node, tree_cons
985 (NULL_TREE, integer_type_node, tree_cons
986 (NULL_TREE, build_pointer_type (type_info_type_node),
988 tmp = build_function_type (void_type_node, tmp);
990 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
991 DECL_EXTERNAL (fn) = 1;
992 TREE_PUBLIC (fn) = 1;
993 DECL_ARTIFICIAL (fn) = 1;
994 pushdecl_top_level (fn);
995 make_function_rtl (fn);
996 assemble_external (fn);
1000 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1001 expand_expr_stmt (fn);
1004 /* Build an initializer for a type_info node that just has a name. */
1007 expand_generic_desc (tdecl, type, fnname)
1012 char *name = build_overload_name (type, 1, 1);
1013 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1014 tree elems = tree_cons
1015 (NULL_TREE, decay_conversion (tdecl), tree_cons
1016 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1018 tree fn = get_identifier (fnname);
1019 if (IDENTIFIER_GLOBAL_VALUE (fn))
1020 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1024 push_obstacks (&permanent_obstack, &permanent_obstack);
1026 (NULL_TREE, ptr_type_node, tree_cons
1027 (NULL_TREE, const_string_type_node, void_list_node));
1028 tmp = build_function_type (void_type_node, tmp);
1030 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1031 DECL_EXTERNAL (fn) = 1;
1032 TREE_PUBLIC (fn) = 1;
1033 DECL_ARTIFICIAL (fn) = 1;
1034 pushdecl_top_level (fn);
1035 make_function_rtl (fn);
1036 assemble_external (fn);
1040 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1041 expand_expr_stmt (fn);
1044 /* Generate the code for a type_info initialization function.
1045 Note that we take advantage of the passage
1047 5.2.7 Type identification [expr.typeid]
1049 Whether or not the destructor is called for the type_info object at the
1050 end of the program is unspecified.
1052 and don't bother to arrange for these objects to be destroyed. It
1053 doesn't matter, anyway, since the destructors don't do anything.
1055 This must only be called from toplevel (i.e. from finish_file)! */
1058 synthesize_tinfo_fn (fndecl)
1061 tree type = TREE_TYPE (DECL_NAME (fndecl));
1064 tree tdecl = get_tinfo_var (type);
1065 DECL_EXTERNAL (tdecl) = 0;
1066 TREE_STATIC (tdecl) = 1;
1067 DECL_COMMON (tdecl) = 1;
1068 TREE_USED (tdecl) = 1;
1069 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1070 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1072 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1073 store_parm_decls ();
1077 /* If the first word of the array (the vtable) is non-zero, we've already
1078 initialized the object, so don't do it again. */
1079 addr = decay_conversion (tdecl);
1080 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1081 tmp = build_indirect_ref (tmp, 0);
1082 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1083 expand_start_cond (tmp, 0);
1085 if (TREE_CODE (type) == FUNCTION_TYPE)
1086 expand_generic_desc (tdecl, type, "__rtti_func");
1087 else if (TREE_CODE (type) == ARRAY_TYPE)
1088 expand_generic_desc (tdecl, type, "__rtti_array");
1089 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1090 expand_attr_desc (tdecl, type);
1091 else if (TREE_CODE (type) == POINTER_TYPE)
1093 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1094 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1095 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1096 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1098 expand_ptr_desc (tdecl, type);
1100 else if (TYPE_PTRMEMFUNC_P (type))
1101 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1102 else if (IS_AGGR_TYPE (type))
1104 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1105 expand_generic_desc (tdecl, type, "__rtti_user");
1106 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1108 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1109 expand_si_desc (tdecl, type);
1111 expand_class_desc (tdecl, type);
1113 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1114 expand_generic_desc (tdecl, type, "__rtti_user");
1116 my_friendly_abort (252);
1120 /* OK, now return the type_info object. */
1121 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1122 tmp = build_indirect_ref (tmp, 0);
1123 c_expand_return (tmp);
1124 finish_function (lineno, 0, 0);