1 /* RunTime Type Identification
2 Copyright (C) 1995, 96-97, 1998, 1999, 2000 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 tinfo_name
PROTO((tree
));
44 static tree get_base_offset
PROTO((tree
, tree
));
45 static tree build_dynamic_cast_1
PROTO((tree
, tree
));
46 static void expand_si_desc
PROTO((tree
, tree
));
47 static void expand_class_desc
PROTO((tree
, tree
));
48 static void expand_attr_desc
PROTO((tree
, tree
));
49 static void expand_ptr_desc
PROTO((tree
, tree
));
50 static void expand_generic_desc
PROTO((tree
, tree
, const char *));
51 static tree throw_bad_cast
PROTO((void));
52 static tree throw_bad_typeid
PROTO((void));
53 static tree get_tinfo_decl_dynamic
PROTO((tree
));
54 static tree tinfo_from_decl
PROTO((tree
));
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);
66 tinfo_decl_id
= get_identifier ("__tf");
67 tinfo_decl_type
= build_function_type
70 (type_info_type_node
, TYPE_QUAL_CONST
)),
72 tinfo_var_id
= get_identifier ("__ti");
75 /* Given a pointer to an object with at least one virtual table
76 pointer somewhere, return a pointer to a possible sub-object that
77 has a virtual table pointer in it that is the vtable parent for
81 build_headof_sub (exp
)
84 tree type
= TREE_TYPE (TREE_TYPE (exp
));
85 tree basetype
= CLASSTYPE_RTTI (type
);
86 tree binfo
= get_binfo (basetype
, type
, 0);
88 exp
= convert_pointer_to_real (binfo
, exp
);
92 /* Given the expression EXP of type `class *', return the head of the
93 object pointed to by EXP with type cv void*, if the class has any
94 virtual functions (TYPE_POLYMORPHIC_P), else just return the
101 tree type
= TREE_TYPE (exp
);
105 my_friendly_assert (TREE_CODE (type
) == POINTER_TYPE
, 20000112);
106 type
= TREE_TYPE (type
);
108 if (!TYPE_POLYMORPHIC_P (type
))
110 if (CLASSTYPE_COM_INTERFACE (type
))
112 cp_error ("RTTI not supported for COM interface type `%T'", type
);
113 return error_mark_node
;
116 /* If we don't have rtti stuff, get to a sub-object that does. */
117 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp
))))
118 exp
= build_headof_sub (exp
);
120 /* We use this a couple of times below, protect it. */
121 exp
= save_expr (exp
);
123 aref
= build_vtbl_ref (build_indirect_ref (exp
, NULL_PTR
), integer_zero_node
);
125 if (flag_vtable_thunks
)
128 offset
= build_component_ref (aref
, delta_identifier
, NULL_TREE
, 0);
130 type
= build_qualified_type (ptr_type_node
,
131 CP_TYPE_QUALS (TREE_TYPE (exp
)));
132 return build (PLUS_EXPR
, type
, exp
,
133 cp_convert (ptrdiff_type_node
, offset
));
136 /* Build a call to a generic entry point taking and returning void. */
142 tree d
= get_identifier (name
);
145 if (IDENTIFIER_GLOBAL_VALUE (d
))
146 d
= IDENTIFIER_GLOBAL_VALUE (d
);
149 type
= build_function_type (void_type_node
, void_list_node
);
150 d
= build_lang_decl (FUNCTION_DECL
, d
, type
);
151 DECL_EXTERNAL (d
) = 1;
153 DECL_ARTIFICIAL (d
) = 1;
154 pushdecl_top_level (d
);
155 make_function_rtl (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 a pointer to type_info function associated with the expression EXP.
179 If EXP is a reference to a polymorphic class, return the dynamic type;
180 otherwise return the static type of the expression. */
183 get_tinfo_decl_dynamic (exp
)
188 if (exp
== error_mark_node
)
189 return error_mark_node
;
191 type
= TREE_TYPE (exp
);
193 /* peel back references, so they match. */
194 if (TREE_CODE (type
) == REFERENCE_TYPE
)
195 type
= TREE_TYPE (type
);
197 /* Peel off cv qualifiers. */
198 type
= TYPE_MAIN_VARIANT (type
);
200 if (type
!= void_type_node
)
201 type
= complete_type_or_else (type
, exp
);
204 return error_mark_node
;
206 /* If exp is a reference to polymorphic type, get the real type_info. */
207 if (TYPE_POLYMORPHIC_P (type
) && ! resolves_to_fixed_type_p (exp
, 0))
209 /* build reference to type_info from vtable. */
213 error ("taking dynamic typeid of object with -fno-rtti");
214 if (CLASSTYPE_COM_INTERFACE (type
))
216 cp_error ("RTTI not supported for COM interface type `%T'", type
);
217 return error_mark_node
;
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_decl_type
);
236 /* otherwise return the type_info for the static type of the expr. */
237 exp
= get_tinfo_decl (TYPE_MAIN_VARIANT (type
));
238 return build_unary_op (ADDR_EXPR
, exp
, 0);
245 tree cond
= NULL_TREE
;
250 error ("cannot use typeid with -fno-rtti");
251 return error_mark_node
;
254 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
256 error ("must #include <typeinfo> before using typeid");
257 return error_mark_node
;
260 if (processing_template_decl
)
261 return build_min_nt (TYPEID_EXPR
, exp
);
263 if (TREE_CODE (exp
) == INDIRECT_REF
264 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp
, 0))) == POINTER_TYPE
265 && TYPE_POLYMORPHIC_P (TREE_TYPE (exp
))
266 && ! resolves_to_fixed_type_p (exp
, &nonnull
)
269 exp
= stabilize_reference (exp
);
270 cond
= cp_convert (boolean_type_node
, TREE_OPERAND (exp
, 0));
273 exp
= get_tinfo_decl_dynamic (exp
);
275 if (exp
== error_mark_node
)
276 return error_mark_node
;
278 exp
= tinfo_from_decl (exp
);
282 tree bad
= throw_bad_typeid ();
284 exp
= build (COND_EXPR
, TREE_TYPE (exp
), cond
, exp
, bad
);
287 return convert_from_reference (exp
);
294 tree tname
= build_overload_with_type (tinfo_var_id
, type
);
298 if (IDENTIFIER_GLOBAL_VALUE (tname
))
299 return IDENTIFIER_GLOBAL_VALUE (tname
);
301 /* Figure out how much space we need to allocate for the type_info object.
302 If our struct layout or the type_info classes are changed, this will
303 need to be modified. */
304 if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
305 size
= 3 * POINTER_SIZE
+ INT_TYPE_SIZE
;
306 else if (TREE_CODE (type
) == POINTER_TYPE
307 && ! (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
308 || TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
))
309 size
= 3 * POINTER_SIZE
;
310 else if (IS_AGGR_TYPE (type
))
312 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
313 size
= 2 * POINTER_SIZE
;
314 else if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type
)
316 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
317 size
= 3 * POINTER_SIZE
;
319 size
= 3 * POINTER_SIZE
+ TYPE_PRECISION (sizetype
);
322 size
= 2 * POINTER_SIZE
;
324 /* The type for a character array of the appropriate size. */
325 arrtype
= build_cplus_array_type
326 (unsigned_char_type_node
,
327 build_index_type (size_int (size
/ BITS_PER_UNIT
- 1)));
329 return declare_global_var (tname
, arrtype
);
332 /* Generate the NTBS name of a type. */
337 const char *name
= build_overload_name (type
, 1, 1);
338 tree name_string
= combine_strings (build_string (strlen (name
) + 1, name
));
342 /* Returns a decl for a function or variable which can be used to obtain a
343 type_info object for TYPE. The old-abi uses functions, the new-abi will
344 use the type_info object directly. You can take the address of the
345 returned decl, to save the decl. To use the decl call
346 tinfo_from_decl. You must arrange that the decl is mark_used, if
347 actually use it --- decls in vtables are only used if the vtable is
351 get_tinfo_decl (type
)
357 if (TREE_CODE (type
) == OFFSET_TYPE
)
358 type
= TREE_TYPE (type
);
359 if (TREE_CODE (type
) == METHOD_TYPE
)
360 type
= build_function_type (TREE_TYPE (type
),
361 TREE_CHAIN (TYPE_ARG_TYPES (type
)));
363 name
= build_overload_with_type (tinfo_decl_id
, type
);
365 if (IDENTIFIER_GLOBAL_VALUE (name
))
366 return IDENTIFIER_GLOBAL_VALUE (name
);
368 d
= build_lang_decl (FUNCTION_DECL
, name
, tinfo_decl_type
);
369 DECL_EXTERNAL (d
) = 1;
371 DECL_ARTIFICIAL (d
) = 1;
372 DECL_NOT_REALLY_EXTERN (d
) = 1;
373 SET_DECL_TINFO_FN_P (d
);
374 TREE_TYPE (name
) = type
;
376 pushdecl_top_level (d
);
377 make_function_rtl (d
);
378 mark_inline_for_output (d
);
383 /* Given an expr produced by get_tinfo_decl, return an expr which
384 produces a reference to the type_info object. */
387 tinfo_from_decl (expr
)
390 tree t
= build_call (expr
, TREE_TYPE (tinfo_decl_type
), NULL_TREE
);
401 t
= get_tinfo_decl (type
);
402 t
= tinfo_from_decl (t
);
403 return convert_from_reference (t
);
406 /* Return the type_info object for TYPE. */
412 if (type
== error_mark_node
)
413 return error_mark_node
;
415 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
417 error ("must #include <typeinfo> before using typeid");
418 return error_mark_node
;
421 if (processing_template_decl
)
422 return build_min_nt (TYPEID_EXPR
, type
);
424 /* If the type of the type-id is a reference type, the result of the
425 typeid expression refers to a type_info object representing the
427 if (TREE_CODE (type
) == REFERENCE_TYPE
)
428 type
= TREE_TYPE (type
);
430 /* The top-level cv-qualifiers of the lvalue expression or the type-id
431 that is the operand of typeid are always ignored. */
432 type
= TYPE_MAIN_VARIANT (type
);
434 if (type
!= void_type_node
)
435 type
= complete_type_or_else (type
, NULL_TREE
);
438 return error_mark_node
;
440 return get_typeid_1 (type
);
443 /* Check whether TEST is null before returning RESULT. If TEST is used in
444 RESULT, it must have previously had a save_expr applied to it. */
447 ifnonnull (test
, result
)
450 return build (COND_EXPR
, TREE_TYPE (result
),
451 build (EQ_EXPR
, boolean_type_node
, test
, integer_zero_node
),
452 cp_convert (TREE_TYPE (result
), integer_zero_node
),
456 /* Generate the constant expression describing where direct base BINFO
457 appears within the PARENT. How to interpret this expression depends on
458 details of the ABI, which the runtime must be aware of. */
461 get_base_offset (binfo
, parent
)
467 if (!TREE_VIA_VIRTUAL (binfo
))
468 offset
= BINFO_OFFSET (binfo
);
469 else if (!vbase_offsets_in_vtable_p ())
471 tree t
= BINFO_TYPE (binfo
);
475 FORMAT_VBASE_NAME (name
, t
);
476 field
= lookup_field (parent
, get_identifier (name
), 0, 0);
477 offset
= size_binop (FLOOR_DIV_EXPR
,
478 DECL_FIELD_BITPOS (field
),
479 size_int (BITS_PER_UNIT
));
480 offset
= convert (sizetype
, offset
);
484 /* Under the new ABI, we store the vtable offset at which
485 the virtual base offset can be found. */
486 tree vbase
= BINFO_FOR_VBASE (BINFO_TYPE (binfo
), parent
);
487 offset
= convert (sizetype
, BINFO_VPTR_FIELD (vbase
));
492 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
496 build_dynamic_cast_1 (type
, expr
)
499 enum tree_code tc
= TREE_CODE (type
);
503 tree old_expr
= expr
;
505 if (TREE_CODE (expr
) == OFFSET_REF
)
506 expr
= resolve_offset_ref (expr
);
508 exprtype
= TREE_TYPE (expr
);
509 assert (exprtype
!= NULL_TREE
);
510 ec
= TREE_CODE (exprtype
);
515 if (ec
== REFERENCE_TYPE
)
517 expr
= convert_from_reference (expr
);
518 exprtype
= TREE_TYPE (expr
);
519 ec
= TREE_CODE (exprtype
);
521 if (ec
!= POINTER_TYPE
)
523 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
525 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
527 if (!at_least_as_qualified_p (TREE_TYPE (type
),
528 TREE_TYPE (exprtype
)))
530 if (TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
532 /* else fall through */
534 if (TREE_CODE (TREE_TYPE (type
)) != RECORD_TYPE
)
536 if (TYPE_SIZE (complete_type (TREE_TYPE (type
))) == NULL_TREE
)
539 /* else fall through */
544 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
545 if (ec
== RECORD_TYPE
)
547 exprtype
= build_reference_type (exprtype
);
548 expr
= convert_to_reference (exprtype
, expr
, CONV_IMPLICIT
,
549 LOOKUP_NORMAL
, NULL_TREE
);
553 if (tc
== REFERENCE_TYPE
)
555 if (ec
!= REFERENCE_TYPE
)
557 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
559 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
561 if (!at_least_as_qualified_p (TREE_TYPE (type
),
562 TREE_TYPE (exprtype
)))
566 /* If *type is an unambiguous accessible base class of *exprtype,
567 convert statically. */
572 distance
= get_base_distance (TREE_TYPE (type
), TREE_TYPE (exprtype
), 1,
577 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
578 TREE_TYPE (exprtype
), TREE_TYPE (type
));
579 return error_mark_node
;
583 cp_error ("dynamic_cast from `%T' to private base class `%T'",
584 TREE_TYPE (exprtype
), TREE_TYPE (type
));
585 return error_mark_node
;
589 return build_vbase_path (PLUS_EXPR
, type
, expr
, path
, 0);
592 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
593 if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype
)))
596 /* if TYPE is `void *', return pointer to complete object. */
597 if (tc
== POINTER_TYPE
598 && TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
600 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
601 if (TREE_CODE (expr
) == ADDR_EXPR
602 && TREE_CODE (TREE_OPERAND (expr
, 0)) == VAR_DECL
603 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == RECORD_TYPE
)
604 return build1 (NOP_EXPR
, type
, expr
);
606 /* Since expr is used twice below, save it. */
607 expr
= save_expr (expr
);
609 expr1
= build_headof (expr
);
610 if (TREE_TYPE (expr1
) != type
)
611 expr1
= build1 (NOP_EXPR
, type
, expr1
);
612 return ifnonnull (expr
, expr1
);
617 tree result
, td1
, td2
, td3
, elems
, expr2
;
618 tree static_type
, target_type
, boff
;
620 /* If we got here, we can't convert statically. Therefore,
621 dynamic_cast<D&>(b) (b an object) cannot succeed. */
622 if (ec
== REFERENCE_TYPE
)
624 if (TREE_CODE (old_expr
) == VAR_DECL
625 && TREE_CODE (TREE_TYPE (old_expr
)) == RECORD_TYPE
)
627 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
629 return throw_bad_cast ();
632 /* Ditto for dynamic_cast<D*>(&b). */
633 else if (TREE_CODE (expr
) == ADDR_EXPR
)
635 tree op
= TREE_OPERAND (expr
, 0);
636 if (TREE_CODE (op
) == VAR_DECL
637 && TREE_CODE (TREE_TYPE (op
)) == RECORD_TYPE
)
639 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
641 retval
= build_int_2 (0, 0);
642 TREE_TYPE (retval
) = type
;
647 /* Since expr is used twice below, save it. */
648 expr
= save_expr (expr
);
651 if (tc
== REFERENCE_TYPE
)
652 expr1
= build_unary_op (ADDR_EXPR
, expr1
, 0);
654 /* Build run-time conversion. */
655 expr2
= build_headof (expr1
);
657 if (ec
== POINTER_TYPE
)
658 td1
= get_tinfo_decl_dynamic (build_indirect_ref (expr
, NULL_PTR
));
660 td1
= get_tinfo_decl_dynamic (expr
);
661 td1
= decay_conversion (td1
);
663 target_type
= TYPE_MAIN_VARIANT (TREE_TYPE (type
));
664 static_type
= TYPE_MAIN_VARIANT (TREE_TYPE (exprtype
));
665 td2
= decay_conversion (get_tinfo_decl (target_type
));
666 td3
= decay_conversion (get_tinfo_decl (static_type
));
668 /* Determine how T and V are related. */
669 boff
= get_dynamic_cast_base_type (static_type
, target_type
);
672 (NULL_TREE
, td1
, tree_cons
673 (NULL_TREE
, td2
, tree_cons
674 (NULL_TREE
, boff
, tree_cons
675 (NULL_TREE
, expr2
, tree_cons
676 (NULL_TREE
, td3
, tree_cons
677 (NULL_TREE
, expr1
, NULL_TREE
))))));
679 dcast_fn
= get_identifier ("__dynamic_cast_2");
680 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn
))
681 dcast_fn
= IDENTIFIER_GLOBAL_VALUE (dcast_fn
);
687 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
688 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
689 (NULL_TREE
, integer_type_node
, tree_cons
690 (NULL_TREE
, ptr_type_node
, tree_cons
691 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
692 (NULL_TREE
, ptr_type_node
, void_list_node
))))));
693 tmp
= build_function_type (ptr_type_node
, tmp
);
694 dcast_fn
= build_lang_decl (FUNCTION_DECL
, dcast_fn
, tmp
);
695 DECL_EXTERNAL (dcast_fn
) = 1;
696 TREE_PUBLIC (dcast_fn
) = 1;
697 DECL_ARTIFICIAL (dcast_fn
) = 1;
698 pushdecl_top_level (dcast_fn
);
699 make_function_rtl (dcast_fn
);
702 mark_used (dcast_fn
);
704 (dcast_fn
, TREE_TYPE (TREE_TYPE (dcast_fn
)), elems
);
706 if (tc
== REFERENCE_TYPE
)
708 expr1
= throw_bad_cast ();
709 result
= save_expr (result
);
710 return build (COND_EXPR
, type
, result
, result
, expr1
);
713 /* Now back to the type we want from a void*. */
714 result
= cp_convert (type
, result
);
715 return ifnonnull (expr
, result
);
719 cp_error ("dynamic_cast from non-polymorphic type `%#T'", exprtype
);
720 return error_mark_node
;
723 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
724 expr
, exprtype
, type
);
725 return error_mark_node
;
729 build_dynamic_cast (type
, expr
)
732 if (type
== error_mark_node
|| expr
== error_mark_node
)
733 return error_mark_node
;
735 if (processing_template_decl
)
736 return build_min (DYNAMIC_CAST_EXPR
, type
, expr
);
738 return convert_from_reference (build_dynamic_cast_1 (type
, expr
));
741 /* Build and initialize various sorts of descriptors. Every descriptor
742 node has a name associated with it (the name created by mangling).
743 For this reason, we use the identifier as our access to the __*_desc
744 nodes, instead of sticking them directly in the types. Otherwise we
745 would burden all built-in types (and pointer types) with slots that
746 we don't necessarily want to use.
748 For each descriptor we build, we build a variable that contains
749 the descriptor's information. When we need this info at runtime,
750 all we need is access to these variables.
752 Note: these constructors always return the address of the descriptor
753 info, since that is simplest for their mutual interaction. */
755 /* Build an initializer for a __si_type_info node. */
758 expand_si_desc (tdecl
, type
)
763 tree name_string
= tinfo_name (type
);
765 type
= BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0));
766 finish_expr_stmt (get_typeid_1 (type
));
767 t
= decay_conversion (get_tinfo_var (type
));
769 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
770 (NULL_TREE
, decay_conversion (name_string
), tree_cons
771 (NULL_TREE
, t
, NULL_TREE
)));
773 fn
= get_identifier ("__rtti_si");
774 if (IDENTIFIER_GLOBAL_VALUE (fn
))
775 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
780 (NULL_TREE
, ptr_type_node
, tree_cons
781 (NULL_TREE
, const_string_type_node
, tree_cons
782 (NULL_TREE
, build_pointer_type (type_info_type_node
),
784 tmp
= build_function_type (void_type_node
, tmp
);
786 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
787 DECL_EXTERNAL (fn
) = 1;
788 TREE_PUBLIC (fn
) = 1;
789 DECL_ARTIFICIAL (fn
) = 1;
790 pushdecl_top_level (fn
);
791 make_function_rtl (fn
);
795 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
796 finish_expr_stmt (fn
);
799 /* Build an initializer for a __class_type_info node. */
802 expand_class_desc (tdecl
, type
)
809 int i
= CLASSTYPE_N_BASECLASSES (type
);
811 tree binfos
= TYPE_BINFO_BASETYPES (type
);
813 /* See code below that used these. */
814 tree vb
= CLASSTYPE_VBASECLASSES (type
);
817 tree base
, elems
, access
, offset
, isvir
;
818 tree elt
, elts
= NULL_TREE
;
820 if (base_desc_type_node
== NULL_TREE
)
824 /* A reasonably close approximation of __class_type_info::base_info */
826 base_desc_type_node
= make_aggr_type (RECORD_TYPE
);
828 /* Actually const __user_type_info * */
829 fields
[0] = build_lang_decl
830 (FIELD_DECL
, NULL_TREE
,
831 build_pointer_type (build_qualified_type
832 (type_info_type_node
,
834 fields
[1] = build_lang_decl
835 (FIELD_DECL
, NULL_TREE
,
836 flag_new_abi
? intSI_type_node
: unsigned_intSI_type_node
);
837 DECL_BIT_FIELD (fields
[1]) = 1;
838 DECL_FIELD_SIZE (fields
[1]) = 29;
840 fields
[2] = build_lang_decl
841 (FIELD_DECL
, NULL_TREE
, boolean_type_node
);
842 DECL_BIT_FIELD (fields
[2]) = 1;
843 DECL_FIELD_SIZE (fields
[2]) = 1;
845 /* Actually enum access */
846 fields
[3] = build_lang_decl
847 (FIELD_DECL
, NULL_TREE
, integer_type_node
);
848 DECL_BIT_FIELD (fields
[3]) = 1;
849 DECL_FIELD_SIZE (fields
[3]) = 2;
851 finish_builtin_type (base_desc_type_node
, "__base_info", fields
,
857 tree binfo
= TREE_VEC_ELT (binfos
, i
);
859 finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo
)));
860 base
= decay_conversion (get_tinfo_var (BINFO_TYPE (binfo
)));
861 offset
= get_base_offset (binfo
, type
);
863 if (TREE_VIA_PUBLIC (binfo
))
864 access
= access_public_node
;
865 else if (TREE_VIA_PROTECTED (binfo
))
866 access
= access_protected_node
;
868 access
= access_private_node
;
869 if (TREE_VIA_VIRTUAL (binfo
))
870 isvir
= boolean_true_node
;
872 isvir
= boolean_false_node
;
875 (CONSTRUCTOR
, base_desc_type_node
, NULL_TREE
, tree_cons
876 (NULL_TREE
, base
, tree_cons
877 (NULL_TREE
, offset
, tree_cons
878 (NULL_TREE
, isvir
, tree_cons
879 (NULL_TREE
, access
, NULL_TREE
)))));
880 TREE_HAS_CONSTRUCTOR (elt
) = TREE_CONSTANT (elt
) = TREE_STATIC (elt
) = 1;
881 elts
= tree_cons (NULL_TREE
, elt
, elts
);
889 access
= access_public_node
;
892 b
= TREE_VEC_ELT (binfos
, i
);
893 if (BINFO_TYPE (vb
) == BINFO_TYPE (b
) && TREE_VIA_VIRTUAL (b
))
895 if (TREE_VIA_PUBLIC (b
))
896 access
= access_public_node
;
897 else if (TREE_VIA_PROTECTED (b
))
898 access
= access_protected_node
;
900 access
= access_private_node
;
904 base
= build_t_desc (BINFO_TYPE (vb
), 1);
905 offset
= BINFO_OFFSET (vb
);
906 isvir
= build_int_2 (1, 0);
908 base_list
= tree_cons (NULL_TREE
, base
, base_list
);
909 isvir_list
= tree_cons (NULL_TREE
, isvir
, isvir_list
);
910 acc_list
= tree_cons (NULL_TREE
, access
, acc_list
);
911 off_list
= tree_cons (NULL_TREE
, offset
, off_list
);
914 vb
= TREE_CHAIN (vb
);
918 name_string
= tinfo_name (type
);
921 tree arrtype
= build_array_type (base_desc_type_node
, NULL_TREE
);
922 elts
= build (CONSTRUCTOR
, arrtype
, NULL_TREE
, elts
);
923 TREE_HAS_CONSTRUCTOR (elts
) = TREE_CONSTANT (elts
)
924 = TREE_STATIC (elts
) = 1;
925 complete_array_type (arrtype
, elts
, 1);
929 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
930 (NULL_TREE
, decay_conversion (name_string
), tree_cons
931 (NULL_TREE
, decay_conversion (elts
), tree_cons
932 (NULL_TREE
, cp_convert (sizetype
, build_int_2 (base_cnt
, 0)),
935 fn
= get_identifier ("__rtti_class");
936 if (IDENTIFIER_GLOBAL_VALUE (fn
))
937 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
941 (NULL_TREE
, ptr_type_node
, tree_cons
942 (NULL_TREE
, const_string_type_node
, tree_cons
943 (NULL_TREE
, build_pointer_type (base_desc_type_node
), tree_cons
944 (NULL_TREE
, sizetype
, void_list_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
);
956 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
957 finish_expr_stmt (fn
);
960 /* Build an initializer for a __pointer_type_info node. */
963 expand_ptr_desc (tdecl
, type
)
968 tree name_string
= tinfo_name (type
);
970 type
= TREE_TYPE (type
);
971 finish_expr_stmt (get_typeid_1 (type
));
972 t
= decay_conversion (get_tinfo_var (type
));
974 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
975 (NULL_TREE
, decay_conversion (name_string
), tree_cons
976 (NULL_TREE
, t
, NULL_TREE
)));
978 fn
= get_identifier ("__rtti_ptr");
979 if (IDENTIFIER_GLOBAL_VALUE (fn
))
980 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
985 (NULL_TREE
, ptr_type_node
, tree_cons
986 (NULL_TREE
, const_string_type_node
, tree_cons
987 (NULL_TREE
, build_pointer_type (type_info_type_node
),
989 tmp
= build_function_type (void_type_node
, tmp
);
991 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
992 DECL_EXTERNAL (fn
) = 1;
993 TREE_PUBLIC (fn
) = 1;
994 DECL_ARTIFICIAL (fn
) = 1;
995 pushdecl_top_level (fn
);
996 make_function_rtl (fn
);
1000 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1001 finish_expr_stmt (fn
);
1004 /* Build an initializer for a __attr_type_info node. */
1007 expand_attr_desc (tdecl
, type
)
1012 tree name_string
= tinfo_name (type
);
1013 tree attrval
= build_int_2 (TYPE_QUALS (type
), 0);
1015 finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type
)));
1016 t
= decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type
)));
1018 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1019 (NULL_TREE
, decay_conversion (name_string
), tree_cons
1020 (NULL_TREE
, attrval
, tree_cons (NULL_TREE
, t
, NULL_TREE
))));
1022 fn
= get_identifier ("__rtti_attr");
1023 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1024 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1029 (NULL_TREE
, ptr_type_node
, tree_cons
1030 (NULL_TREE
, const_string_type_node
, tree_cons
1031 (NULL_TREE
, integer_type_node
, tree_cons
1032 (NULL_TREE
, build_pointer_type (type_info_type_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
);
1045 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1046 finish_expr_stmt (fn
);
1049 /* Build an initializer for a type_info node that just has a name. */
1052 expand_generic_desc (tdecl
, type
, fnname
)
1057 tree name_string
= tinfo_name (type
);
1058 tree elems
= tree_cons
1059 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1060 (NULL_TREE
, decay_conversion (name_string
), NULL_TREE
));
1062 tree fn
= get_identifier (fnname
);
1063 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1064 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1069 (NULL_TREE
, ptr_type_node
, tree_cons
1070 (NULL_TREE
, const_string_type_node
, void_list_node
));
1071 tmp
= build_function_type (void_type_node
, tmp
);
1073 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1074 DECL_EXTERNAL (fn
) = 1;
1075 TREE_PUBLIC (fn
) = 1;
1076 DECL_ARTIFICIAL (fn
) = 1;
1077 pushdecl_top_level (fn
);
1078 make_function_rtl (fn
);
1082 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1083 finish_expr_stmt (fn
);
1086 /* Generate the code for a type_info initialization function.
1087 Note that we take advantage of the passage
1089 5.2.7 Type identification [expr.typeid]
1091 Whether or not the destructor is called for the type_info object at the
1092 end of the program is unspecified.
1094 and don't bother to arrange for these objects to be destroyed. It
1095 doesn't matter, anyway, since the destructors don't do anything.
1097 This must only be called from toplevel (i.e. from finish_file)! */
1100 synthesize_tinfo_fn (fndecl
)
1103 tree type
= TREE_TYPE (DECL_NAME (fndecl
));
1104 tree tmp
, addr
, tdecl
;
1111 import_export_decl (fndecl
);
1112 if (DECL_REALLY_EXTERN (fndecl
))
1116 /* Declare the static typeinfo variable. */
1117 tdecl
= get_tinfo_var (type
);
1118 DECL_EXTERNAL (tdecl
) = 0;
1119 TREE_STATIC (tdecl
) = 1;
1120 DECL_COMMON (tdecl
) = 1;
1121 TREE_USED (tdecl
) = 1;
1122 DECL_ALIGN (tdecl
) = TYPE_ALIGN (ptr_type_node
);
1123 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0);
1125 /* Begin processing the function. */
1126 start_function (NULL_TREE
, fndecl
, NULL_TREE
,
1127 SF_DEFAULT
| SF_PRE_PARSED
);
1128 DECL_DEFER_OUTPUT (fndecl
) = 1;
1129 store_parm_decls ();
1132 /* Begin the body of the function. */
1133 compound_stmt
= begin_compound_stmt (/*has_no_scope=*/0);
1135 /* For convenience, we save away the address of the static
1137 addr
= decay_conversion (tdecl
);
1139 /* If the first word of the array (the vtable) is non-zero, we've already
1140 initialized the object, so don't do it again. */
1141 if_stmt
= begin_if_stmt ();
1142 tmp
= cp_convert (build_pointer_type (ptr_type_node
), addr
);
1143 tmp
= build_indirect_ref (tmp
, 0);
1144 tmp
= build_binary_op (EQ_EXPR
, tmp
, integer_zero_node
);
1145 finish_if_stmt_cond (tmp
, if_stmt
);
1146 then_clause
= begin_compound_stmt (/*has_no_scope=*/0);
1148 if (TREE_CODE (type
) == FUNCTION_TYPE
)
1149 expand_generic_desc (tdecl
, type
, "__rtti_func");
1150 else if (TREE_CODE (type
) == ARRAY_TYPE
)
1151 expand_generic_desc (tdecl
, type
, "__rtti_array");
1152 else if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
1153 expand_attr_desc (tdecl
, type
);
1154 else if (TREE_CODE (type
) == POINTER_TYPE
)
1156 if (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
)
1157 expand_generic_desc (tdecl
, type
, "__rtti_ptmd");
1158 else if (TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
)
1159 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1161 expand_ptr_desc (tdecl
, type
);
1163 else if (TYPE_PTRMEMFUNC_P (type
))
1164 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1165 else if (IS_AGGR_TYPE (type
))
1167 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
1168 expand_generic_desc (tdecl
, type
, "__rtti_user");
1169 else if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type
)
1171 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
1172 expand_si_desc (tdecl
, type
);
1174 expand_class_desc (tdecl
, type
);
1176 else if (TREE_CODE (type
) == ENUMERAL_TYPE
)
1177 expand_generic_desc (tdecl
, type
, "__rtti_user");
1179 my_friendly_abort (252);
1181 finish_compound_stmt (/*has_no_scope=*/0, then_clause
);
1182 finish_then_clause (if_stmt
);
1185 /* OK, now return the type_info object. */
1186 tmp
= cp_convert (build_pointer_type (type_info_type_node
), addr
);
1187 tmp
= build_indirect_ref (tmp
, 0);
1188 finish_return_stmt (tmp
);
1189 /* Finish the function body. */
1190 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt
);
1191 expand_body (finish_function (lineno
, 0));