1 /* RunTime Type Identification
2 Copyright (C) 1995, 96-97, 1998, 1999 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((const 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 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
, const 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 ()
60 push_namespace (get_identifier ("std"));
61 type_info_type_node
= xref_tag
62 (class_type_node
, get_identifier ("type_info"), 1);
65 tinfo_fn_id
= get_identifier ("__tf");
66 tinfo_fn_type
= build_function_type
67 (build_reference_type (build_qualified_type (type_info_type_node
,
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_qualified_type (ptr_type_node
,
127 CP_TYPE_QUALS (TREE_TYPE (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
);
158 return build_call (d
, void_type_node
, NULL_TREE
);
161 /* Get a bad_cast node for the program to throw...
163 See libstdc++/exception.cc for __throw_bad_cast */
168 return call_void_fn ("__throw_bad_cast");
174 return call_void_fn ("__throw_bad_typeid");
177 /* Return the type_info function associated with the expression EXP. If
178 EXP is a reference to a polymorphic class, return the dynamic type;
179 otherwise return the static type of the expression. */
182 get_tinfo_fn_dynamic (exp
)
187 if (exp
== error_mark_node
)
188 return error_mark_node
;
190 if (type_unknown_p (exp
))
192 error ("typeid of overloaded function");
193 return error_mark_node
;
196 type
= TREE_TYPE (exp
);
198 /* peel back references, so they match. */
199 if (TREE_CODE (type
) == REFERENCE_TYPE
)
200 type
= TREE_TYPE (type
);
202 /* Peel off cv qualifiers. */
203 type
= TYPE_MAIN_VARIANT (type
);
205 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
207 cp_error ("taking typeid of incomplete type `%T'", type
);
208 return error_mark_node
;
211 /* If exp is a reference to polymorphic type, get the real type_info. */
212 if (TYPE_VIRTUAL_P (type
) && ! resolves_to_fixed_type_p (exp
, 0))
214 /* build reference to type_info from vtable. */
218 error ("taking dynamic typeid of object with -fno-rtti");
220 /* If we don't have rtti stuff, get to a sub-object that does. */
221 if (! CLASSTYPE_VFIELDS (type
))
223 exp
= build_unary_op (ADDR_EXPR
, exp
, 0);
224 exp
= build_headof_sub (exp
);
225 exp
= build_indirect_ref (exp
, NULL_PTR
);
228 if (flag_vtable_thunks
)
229 t
= build_vfn_ref ((tree
*) 0, exp
, integer_one_node
);
231 t
= build_vfn_ref ((tree
*) 0, exp
, integer_zero_node
);
232 TREE_TYPE (t
) = build_pointer_type (tinfo_fn_type
);
236 /* otherwise return the type_info for the static type of the expr. */
237 return get_tinfo_fn (TYPE_MAIN_VARIANT (type
));
244 exp
= get_tinfo_fn_dynamic (exp
);
245 exp
= build_call (exp
, TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
246 return convert_from_reference (exp
);
253 tree cond
= NULL_TREE
;
254 tree type
= TREE_TYPE (tinfo_fn_type
);
257 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
259 error ("must #include <typeinfo> before using typeid");
260 return error_mark_node
;
263 if (processing_template_decl
)
264 return build_min_nt (TYPEID_EXPR
, exp
);
266 if (TREE_CODE (exp
) == INDIRECT_REF
267 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp
, 0))) == POINTER_TYPE
268 && TYPE_VIRTUAL_P (TREE_TYPE (exp
))
269 && ! resolves_to_fixed_type_p (exp
, &nonnull
)
272 exp
= stabilize_reference (exp
);
273 cond
= cp_convert (boolean_type_node
, TREE_OPERAND (exp
, 0));
276 exp
= get_tinfo_fn_dynamic (exp
);
278 if (exp
== error_mark_node
)
279 return error_mark_node
;
281 exp
= build_call (exp
, type
, NULL_TREE
);
285 tree bad
= throw_bad_typeid ();
287 bad
= build_compound_expr
288 (expr_tree_cons (NULL_TREE
, bad
, build_expr_list
289 (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
290 exp
= build (COND_EXPR
, type
, cond
, exp
, bad
);
293 return convert_from_reference (exp
);
300 tree tname
= build_overload_with_type (get_identifier ("__ti"), type
);
304 if (IDENTIFIER_GLOBAL_VALUE (tname
))
305 return IDENTIFIER_GLOBAL_VALUE (tname
);
307 /* Figure out how much space we need to allocate for the type_info object.
308 If our struct layout or the type_info classes are changed, this will
309 need to be modified. */
310 if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
311 size
= 3 * POINTER_SIZE
+ INT_TYPE_SIZE
;
312 else if (TREE_CODE (type
) == POINTER_TYPE
313 && ! (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
314 || TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
))
315 size
= 3 * POINTER_SIZE
;
316 else if (IS_AGGR_TYPE (type
))
318 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
319 size
= 2 * POINTER_SIZE
;
320 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
322 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
323 size
= 3 * POINTER_SIZE
;
325 size
= 3 * POINTER_SIZE
+ TYPE_PRECISION (sizetype
);
328 size
= 2 * POINTER_SIZE
;
330 push_obstacks (&permanent_obstack
, &permanent_obstack
);
332 /* The type for a character array of the appropriate size. */
333 arrtype
= build_cplus_array_type
334 (unsigned_char_type_node
,
335 build_index_type (size_int (size
/ BITS_PER_UNIT
- 1)));
337 tdecl
= build_decl (VAR_DECL
, tname
, arrtype
);
338 TREE_PUBLIC (tdecl
) = 1;
339 DECL_EXTERNAL (tdecl
) = 1;
340 DECL_ARTIFICIAL (tdecl
) = 1;
341 pushdecl_top_level (tdecl
);
342 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
356 if (TREE_CODE (type
) == OFFSET_TYPE
)
357 type
= TREE_TYPE (type
);
358 if (TREE_CODE (type
) == METHOD_TYPE
)
359 type
= build_function_type (TREE_TYPE (type
),
360 TREE_CHAIN (TYPE_ARG_TYPES (type
)));
362 name
= build_overload_with_type (tinfo_fn_id
, type
);
364 if (IDENTIFIER_GLOBAL_VALUE (name
))
365 return IDENTIFIER_GLOBAL_VALUE (name
);
367 push_obstacks (&permanent_obstack
, &permanent_obstack
);
369 d
= build_lang_decl (FUNCTION_DECL
, name
, tinfo_fn_type
);
370 DECL_EXTERNAL (d
) = 1;
372 DECL_ARTIFICIAL (d
) = 1;
373 DECL_NOT_REALLY_EXTERN (d
) = 1;
374 DECL_MUTABLE_P (d
) = 1;
375 TREE_TYPE (name
) = copy_to_permanent (type
);
377 pushdecl_top_level (d
);
378 make_function_rtl (d
);
380 mark_inline_for_output (d
);
393 (get_tinfo_fn (type
), TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
394 return convert_from_reference (t
);
397 /* Return the type_info object for TYPE, creating it if necessary. */
403 if (type
== error_mark_node
)
404 return error_mark_node
;
406 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
408 error ("must #include <typeinfo> before using typeid");
409 return error_mark_node
;
413 error ("requesting typeid with -fno-rtti");
415 if (processing_template_decl
)
416 return build_min_nt (TYPEID_EXPR
, type
);
418 /* If the type of the type-id is a reference type, the result of the
419 typeid expression refers to a type_info object representing the
421 if (TREE_CODE (type
) == REFERENCE_TYPE
)
422 type
= TREE_TYPE (type
);
424 /* The top-level cv-qualifiers of the lvalue expression or the type-id
425 that is the operand of typeid are always ignored. */
426 type
= TYPE_MAIN_VARIANT (type
);
428 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
430 cp_error ("taking typeid of incomplete type `%T'", type
);
431 return error_mark_node
;
434 return get_typeid_1 (type
);
437 /* Check whether TEST is null before returning RESULT. If TEST is used in
438 RESULT, it must have previously had a save_expr applied to it. */
441 ifnonnull (test
, result
)
444 return build (COND_EXPR
, TREE_TYPE (result
),
445 build (EQ_EXPR
, boolean_type_node
, test
, integer_zero_node
),
446 cp_convert (TREE_TYPE (result
), integer_zero_node
),
450 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
454 build_dynamic_cast_1 (type
, expr
)
457 enum tree_code tc
= TREE_CODE (type
);
461 tree old_expr
= expr
;
463 if (TREE_CODE (expr
) == OFFSET_REF
)
464 expr
= resolve_offset_ref (expr
);
466 exprtype
= TREE_TYPE (expr
);
467 assert (exprtype
!= NULL_TREE
);
468 ec
= TREE_CODE (exprtype
);
473 if (ec
== REFERENCE_TYPE
)
475 expr
= convert_from_reference (expr
);
476 exprtype
= TREE_TYPE (expr
);
477 ec
= TREE_CODE (exprtype
);
479 if (ec
!= POINTER_TYPE
)
481 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
483 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
485 if (!at_least_as_qualified_p (TREE_TYPE (type
),
486 TREE_TYPE (exprtype
)))
488 if (TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
490 /* else fall through */
492 if (TREE_CODE (TREE_TYPE (type
)) != RECORD_TYPE
)
494 if (TYPE_SIZE (complete_type (TREE_TYPE (type
))) == NULL_TREE
)
497 /* else fall through */
502 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
503 if (ec
== RECORD_TYPE
)
505 exprtype
= build_reference_type (exprtype
);
506 expr
= convert_to_reference (exprtype
, expr
, CONV_IMPLICIT
,
507 LOOKUP_NORMAL
, NULL_TREE
);
511 if (tc
== REFERENCE_TYPE
)
513 if (ec
!= REFERENCE_TYPE
)
515 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
517 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
519 if (!at_least_as_qualified_p (TREE_TYPE (type
),
520 TREE_TYPE (exprtype
)))
524 /* If *type is an unambiguous accessible base class of *exprtype,
525 convert statically. */
530 distance
= get_base_distance (TREE_TYPE (type
), TREE_TYPE (exprtype
), 1,
535 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
536 TREE_TYPE (exprtype
), TREE_TYPE (type
));
537 return error_mark_node
;
541 cp_error ("dynamic_cast from `%T' to private base class `%T'",
542 TREE_TYPE (exprtype
), TREE_TYPE (type
));
543 return error_mark_node
;
547 return build_vbase_path (PLUS_EXPR
, type
, expr
, path
, 0);
550 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
551 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype
)))
554 /* if TYPE is `void *', return pointer to complete object. */
555 if (tc
== POINTER_TYPE
556 && TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
558 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
559 if (TREE_CODE (expr
) == ADDR_EXPR
560 && TREE_CODE (TREE_OPERAND (expr
, 0)) == VAR_DECL
561 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == RECORD_TYPE
)
562 return build1 (NOP_EXPR
, type
, expr
);
564 /* Since expr is used twice below, save it. */
565 expr
= save_expr (expr
);
567 expr1
= build_headof (expr
);
568 if (TREE_TYPE (expr1
) != type
)
569 expr1
= build1 (NOP_EXPR
, type
, expr1
);
570 return ifnonnull (expr
, expr1
);
575 tree result
, td1
, td2
, td3
, elems
, expr2
;
577 /* If we got here, we can't convert statically. Therefore,
578 dynamic_cast<D&>(b) (b an object) cannot succeed. */
579 if (ec
== REFERENCE_TYPE
)
581 if (TREE_CODE (old_expr
) == VAR_DECL
582 && TREE_CODE (TREE_TYPE (old_expr
)) == RECORD_TYPE
)
584 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
586 return throw_bad_cast ();
589 /* Ditto for dynamic_cast<D*>(&b). */
590 else if (TREE_CODE (expr
) == ADDR_EXPR
)
592 tree op
= TREE_OPERAND (expr
, 0);
593 if (TREE_CODE (op
) == VAR_DECL
594 && TREE_CODE (TREE_TYPE (op
)) == RECORD_TYPE
)
596 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
598 retval
= build_int_2 (0, 0);
599 TREE_TYPE (retval
) = type
;
604 /* Since expr is used twice below, save it. */
605 expr
= save_expr (expr
);
608 if (tc
== REFERENCE_TYPE
)
609 expr1
= build_unary_op (ADDR_EXPR
, expr1
, 0);
611 /* Build run-time conversion. */
612 expr2
= build_headof (expr1
);
614 if (ec
== POINTER_TYPE
)
615 td1
= get_tinfo_fn_dynamic (build_indirect_ref (expr
, NULL_PTR
));
617 td1
= get_tinfo_fn_dynamic (expr
);
618 td1
= decay_conversion (td1
);
620 td2
= decay_conversion
621 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type
))));
622 td3
= decay_conversion
623 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype
))));
626 (NULL_TREE
, td1
, tree_cons
627 (NULL_TREE
, td2
, tree_cons
628 (NULL_TREE
, build_int_2 (1, 0), tree_cons
629 (NULL_TREE
, expr2
, tree_cons
630 (NULL_TREE
, td3
, tree_cons
631 (NULL_TREE
, expr1
, NULL_TREE
))))));
633 dcast_fn
= get_identifier ("__dynamic_cast");
634 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn
))
635 dcast_fn
= IDENTIFIER_GLOBAL_VALUE (dcast_fn
);
640 push_obstacks (&permanent_obstack
, &permanent_obstack
);
642 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
643 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
644 (NULL_TREE
, integer_type_node
, tree_cons
645 (NULL_TREE
, ptr_type_node
, tree_cons
646 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
647 (NULL_TREE
, ptr_type_node
, void_list_node
))))));
648 tmp
= build_function_type (ptr_type_node
, tmp
);
649 dcast_fn
= build_lang_decl (FUNCTION_DECL
, dcast_fn
, tmp
);
650 DECL_EXTERNAL (dcast_fn
) = 1;
651 TREE_PUBLIC (dcast_fn
) = 1;
652 DECL_ARTIFICIAL (dcast_fn
) = 1;
653 pushdecl_top_level (dcast_fn
);
654 make_function_rtl (dcast_fn
);
658 mark_used (dcast_fn
);
660 (dcast_fn
, TREE_TYPE (TREE_TYPE (dcast_fn
)), elems
);
662 if (tc
== REFERENCE_TYPE
)
664 expr1
= throw_bad_cast ();
665 expr1
= build_compound_expr
666 (expr_tree_cons (NULL_TREE
, expr1
,
667 build_expr_list (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
668 TREE_TYPE (expr1
) = type
;
669 result
= save_expr (result
);
670 return build (COND_EXPR
, type
, result
, result
, expr1
);
673 /* Now back to the type we want from a void*. */
674 result
= cp_convert (type
, result
);
675 return ifnonnull (expr
, result
);
680 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
681 expr
, exprtype
, type
);
682 return error_mark_node
;
686 build_dynamic_cast (type
, expr
)
689 if (type
== error_mark_node
|| expr
== error_mark_node
)
690 return error_mark_node
;
692 if (processing_template_decl
)
693 return build_min (DYNAMIC_CAST_EXPR
, copy_to_permanent (type
), expr
);
695 return convert_from_reference (build_dynamic_cast_1 (type
, expr
));
698 /* Build and initialize various sorts of descriptors. Every descriptor
699 node has a name associated with it (the name created by mangling).
700 For this reason, we use the identifier as our access to the __*_desc
701 nodes, instead of sticking them directly in the types. Otherwise we
702 would burden all built-in types (and pointer types) with slots that
703 we don't necessarily want to use.
705 For each descriptor we build, we build a variable that contains
706 the descriptor's information. When we need this info at runtime,
707 all we need is access to these variables.
709 Note: these constructors always return the address of the descriptor
710 info, since that is simplest for their mutual interaction. */
712 extern tree const_string_type_node
;
714 /* Build an initializer for a __si_type_info node. */
717 expand_si_desc (tdecl
, type
)
722 const char *name
= build_overload_name (type
, 1, 1);
723 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
725 type
= BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0));
726 expand_expr_stmt (get_typeid_1 (type
));
727 t
= decay_conversion (get_tinfo_var (type
));
729 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
730 (NULL_TREE
, decay_conversion (name_string
), tree_cons
731 (NULL_TREE
, t
, NULL_TREE
)));
733 fn
= get_identifier ("__rtti_si");
734 if (IDENTIFIER_GLOBAL_VALUE (fn
))
735 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
739 push_obstacks (&permanent_obstack
, &permanent_obstack
);
741 (NULL_TREE
, ptr_type_node
, tree_cons
742 (NULL_TREE
, const_string_type_node
, tree_cons
743 (NULL_TREE
, build_pointer_type (type_info_type_node
),
745 tmp
= build_function_type (void_type_node
, tmp
);
747 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
748 DECL_EXTERNAL (fn
) = 1;
749 TREE_PUBLIC (fn
) = 1;
750 DECL_ARTIFICIAL (fn
) = 1;
751 pushdecl_top_level (fn
);
752 make_function_rtl (fn
);
757 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
758 expand_expr_stmt (fn
);
761 /* Build an initializer for a __class_type_info node. */
764 expand_class_desc (tdecl
, type
)
772 int i
= CLASSTYPE_N_BASECLASSES (type
);
774 tree binfos
= TYPE_BINFO_BASETYPES (type
);
776 /* See code below that used these. */
777 tree vb
= CLASSTYPE_VBASECLASSES (type
);
780 tree base
, elems
, access
, offset
, isvir
;
781 tree elt
, elts
= NULL_TREE
;
782 static tree base_info_type_node
;
784 if (base_info_type_node
== NULL_TREE
)
788 /* A reasonably close approximation of __class_type_info::base_info */
790 push_obstacks (&permanent_obstack
, &permanent_obstack
);
791 base_info_type_node
= make_lang_type (RECORD_TYPE
);
793 /* Actually const __user_type_info * */
794 fields
[0] = build_lang_field_decl
795 (FIELD_DECL
, NULL_TREE
,
796 build_pointer_type (build_qualified_type
797 (type_info_type_node
,
799 fields
[1] = build_lang_field_decl
800 (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
801 DECL_BIT_FIELD (fields
[1]) = 1;
802 DECL_FIELD_SIZE (fields
[1]) = 29;
804 fields
[2] = build_lang_field_decl
805 (FIELD_DECL
, NULL_TREE
, boolean_type_node
);
806 DECL_BIT_FIELD (fields
[2]) = 1;
807 DECL_FIELD_SIZE (fields
[2]) = 1;
809 /* Actually enum access */
810 fields
[3] = build_lang_field_decl
811 (FIELD_DECL
, NULL_TREE
, integer_type_node
);
812 DECL_BIT_FIELD (fields
[3]) = 1;
813 DECL_FIELD_SIZE (fields
[3]) = 2;
815 finish_builtin_type (base_info_type_node
, "__base_info", fields
,
822 tree binfo
= TREE_VEC_ELT (binfos
, i
);
824 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo
)));
825 base
= decay_conversion (get_tinfo_var (BINFO_TYPE (binfo
)));
827 if (TREE_VIA_VIRTUAL (binfo
))
829 tree t
= BINFO_TYPE (binfo
);
833 FORMAT_VBASE_NAME (name
, t
);
834 field
= lookup_field (type
, get_identifier (name
), 0, 0);
835 offset
= size_binop (FLOOR_DIV_EXPR
,
836 DECL_FIELD_BITPOS (field
), size_int (BITS_PER_UNIT
));
837 offset
= convert (sizetype
, offset
);
840 offset
= BINFO_OFFSET (binfo
);
842 if (TREE_VIA_PUBLIC (binfo
))
843 access
= access_public_node
;
844 else if (TREE_VIA_PROTECTED (binfo
))
845 access
= access_protected_node
;
847 access
= access_private_node
;
848 if (TREE_VIA_VIRTUAL (binfo
))
849 isvir
= boolean_true_node
;
851 isvir
= boolean_false_node
;
854 (CONSTRUCTOR
, base_info_type_node
, NULL_TREE
, tree_cons
855 (NULL_TREE
, base
, tree_cons
856 (NULL_TREE
, offset
, tree_cons
857 (NULL_TREE
, isvir
, tree_cons
858 (NULL_TREE
, access
, NULL_TREE
)))));
859 TREE_HAS_CONSTRUCTOR (elt
) = TREE_CONSTANT (elt
) = TREE_STATIC (elt
) = 1;
860 elts
= expr_tree_cons (NULL_TREE
, elt
, elts
);
868 access
= access_public_node
;
871 b
= TREE_VEC_ELT (binfos
, i
);
872 if (BINFO_TYPE (vb
) == BINFO_TYPE (b
) && TREE_VIA_VIRTUAL (b
))
874 if (TREE_VIA_PUBLIC (b
))
875 access
= access_public_node
;
876 else if (TREE_VIA_PROTECTED (b
))
877 access
= access_protected_node
;
879 access
= access_private_node
;
883 base
= build_t_desc (BINFO_TYPE (vb
), 1);
884 offset
= BINFO_OFFSET (vb
);
885 isvir
= build_int_2 (1, 0);
887 base_list
= expr_tree_cons (NULL_TREE
, base
, base_list
);
888 isvir_list
= expr_tree_cons (NULL_TREE
, isvir
, isvir_list
);
889 acc_list
= expr_tree_cons (NULL_TREE
, access
, acc_list
);
890 off_list
= expr_tree_cons (NULL_TREE
, offset
, off_list
);
893 vb
= TREE_CHAIN (vb
);
897 name
= build_overload_name (type
, 1, 1);
898 name_string
= combine_strings (build_string (strlen (name
)+1, name
));
901 tree arrtype
= build_array_type (base_info_type_node
, NULL_TREE
);
902 elts
= build (CONSTRUCTOR
, arrtype
, NULL_TREE
, elts
);
903 TREE_HAS_CONSTRUCTOR (elts
) = TREE_CONSTANT (elts
)
904 = TREE_STATIC (elts
) = 1;
905 complete_array_type (arrtype
, elts
, 1);
909 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
910 (NULL_TREE
, decay_conversion (name_string
), tree_cons
911 (NULL_TREE
, decay_conversion (elts
), tree_cons
912 (NULL_TREE
, cp_convert (sizetype
, build_int_2 (base_cnt
, 0)),
915 fn
= get_identifier ("__rtti_class");
916 if (IDENTIFIER_GLOBAL_VALUE (fn
))
917 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
920 push_obstacks (&permanent_obstack
, &permanent_obstack
);
922 (NULL_TREE
, ptr_type_node
, tree_cons
923 (NULL_TREE
, const_string_type_node
, tree_cons
924 (NULL_TREE
, build_pointer_type (base_info_type_node
), tree_cons
925 (NULL_TREE
, sizetype
, void_list_node
))));
926 tmp
= build_function_type (void_type_node
, tmp
);
928 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
929 DECL_EXTERNAL (fn
) = 1;
930 TREE_PUBLIC (fn
) = 1;
931 DECL_ARTIFICIAL (fn
) = 1;
932 pushdecl_top_level (fn
);
933 make_function_rtl (fn
);
938 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
939 expand_expr_stmt (fn
);
942 /* Build an initializer for a __pointer_type_info node. */
945 expand_ptr_desc (tdecl
, type
)
950 const char *name
= build_overload_name (type
, 1, 1);
951 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
953 type
= TREE_TYPE (type
);
954 expand_expr_stmt (get_typeid_1 (type
));
955 t
= decay_conversion (get_tinfo_var (type
));
957 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
958 (NULL_TREE
, decay_conversion (name_string
), tree_cons
959 (NULL_TREE
, t
, NULL_TREE
)));
961 fn
= get_identifier ("__rtti_ptr");
962 if (IDENTIFIER_GLOBAL_VALUE (fn
))
963 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
967 push_obstacks (&permanent_obstack
, &permanent_obstack
);
969 (NULL_TREE
, ptr_type_node
, tree_cons
970 (NULL_TREE
, const_string_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
);
985 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
986 expand_expr_stmt (fn
);
989 /* Build an initializer for a __attr_type_info node. */
992 expand_attr_desc (tdecl
, type
)
997 const char *name
= build_overload_name (type
, 1, 1);
998 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
999 tree attrval
= build_int_2 (TYPE_QUALS (type
), 0);
1001 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type
)));
1002 t
= decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type
)));
1004 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1005 (NULL_TREE
, decay_conversion (name_string
), tree_cons
1006 (NULL_TREE
, attrval
, expr_tree_cons (NULL_TREE
, t
, NULL_TREE
))));
1008 fn
= get_identifier ("__rtti_attr");
1009 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1010 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1014 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1016 (NULL_TREE
, ptr_type_node
, tree_cons
1017 (NULL_TREE
, const_string_type_node
, tree_cons
1018 (NULL_TREE
, integer_type_node
, tree_cons
1019 (NULL_TREE
, build_pointer_type (type_info_type_node
),
1021 tmp
= build_function_type (void_type_node
, tmp
);
1023 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1024 DECL_EXTERNAL (fn
) = 1;
1025 TREE_PUBLIC (fn
) = 1;
1026 DECL_ARTIFICIAL (fn
) = 1;
1027 pushdecl_top_level (fn
);
1028 make_function_rtl (fn
);
1033 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1034 expand_expr_stmt (fn
);
1037 /* Build an initializer for a type_info node that just has a name. */
1040 expand_generic_desc (tdecl
, type
, fnname
)
1045 const char *name
= build_overload_name (type
, 1, 1);
1046 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1047 tree elems
= tree_cons
1048 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1049 (NULL_TREE
, decay_conversion (name_string
), NULL_TREE
));
1051 tree fn
= get_identifier (fnname
);
1052 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1053 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1057 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1059 (NULL_TREE
, ptr_type_node
, tree_cons
1060 (NULL_TREE
, const_string_type_node
, void_list_node
));
1061 tmp
= build_function_type (void_type_node
, tmp
);
1063 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1064 DECL_EXTERNAL (fn
) = 1;
1065 TREE_PUBLIC (fn
) = 1;
1066 DECL_ARTIFICIAL (fn
) = 1;
1067 pushdecl_top_level (fn
);
1068 make_function_rtl (fn
);
1073 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1074 expand_expr_stmt (fn
);
1077 /* Generate the code for a type_info initialization function.
1078 Note that we take advantage of the passage
1080 5.2.7 Type identification [expr.typeid]
1082 Whether or not the destructor is called for the type_info object at the
1083 end of the program is unspecified.
1085 and don't bother to arrange for these objects to be destroyed. It
1086 doesn't matter, anyway, since the destructors don't do anything.
1088 This must only be called from toplevel (i.e. from finish_file)! */
1091 synthesize_tinfo_fn (fndecl
)
1094 tree type
= TREE_TYPE (DECL_NAME (fndecl
));
1095 tree tmp
, addr
, tdecl
;
1099 import_export_decl (fndecl
);
1100 if (DECL_REALLY_EXTERN (fndecl
))
1104 tdecl
= get_tinfo_var (type
);
1105 DECL_EXTERNAL (tdecl
) = 0;
1106 TREE_STATIC (tdecl
) = 1;
1107 DECL_COMMON (tdecl
) = 1;
1108 TREE_USED (tdecl
) = 1;
1109 DECL_ALIGN (tdecl
) = TYPE_ALIGN (ptr_type_node
);
1110 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
1112 start_function (NULL_TREE
, fndecl
, NULL_TREE
, 1);
1113 store_parm_decls ();
1117 /* If the first word of the array (the vtable) is non-zero, we've already
1118 initialized the object, so don't do it again. */
1119 addr
= decay_conversion (tdecl
);
1120 tmp
= cp_convert (build_pointer_type (ptr_type_node
), addr
);
1121 tmp
= build_indirect_ref (tmp
, 0);
1122 tmp
= build_binary_op (EQ_EXPR
, tmp
, integer_zero_node
, 1);
1123 expand_start_cond (tmp
, 0);
1125 if (TREE_CODE (type
) == FUNCTION_TYPE
)
1126 expand_generic_desc (tdecl
, type
, "__rtti_func");
1127 else if (TREE_CODE (type
) == ARRAY_TYPE
)
1128 expand_generic_desc (tdecl
, type
, "__rtti_array");
1129 else if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
1130 expand_attr_desc (tdecl
, type
);
1131 else if (TREE_CODE (type
) == POINTER_TYPE
)
1133 if (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
)
1134 expand_generic_desc (tdecl
, type
, "__rtti_ptmd");
1135 else if (TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
)
1136 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1138 expand_ptr_desc (tdecl
, type
);
1140 else if (TYPE_PTRMEMFUNC_P (type
))
1141 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1142 else if (IS_AGGR_TYPE (type
))
1144 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
1145 expand_generic_desc (tdecl
, type
, "__rtti_user");
1146 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
1148 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
1149 expand_si_desc (tdecl
, type
);
1151 expand_class_desc (tdecl
, type
);
1153 else if (TREE_CODE (type
) == ENUMERAL_TYPE
)
1154 expand_generic_desc (tdecl
, type
, "__rtti_user");
1156 my_friendly_abort (252);
1160 /* OK, now return the type_info object. */
1161 tmp
= cp_convert (build_pointer_type (type_info_type_node
), addr
);
1162 tmp
= build_indirect_ref (tmp
, 0);
1163 c_expand_return (tmp
);
1164 finish_function (lineno
, 0, 0);