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));
53 init_rtti_processing ()
56 push_namespace (get_identifier ("std"));
57 type_info_type_node
= xref_tag
58 (class_type_node
, get_identifier ("type_info"), 1);
61 tinfo_fn_id
= get_identifier ("__tf");
62 tinfo_fn_type
= build_function_type
63 (build_reference_type (build_qualified_type (type_info_type_node
,
68 /* Given a pointer to an object with at least one virtual table
69 pointer somewhere, return a pointer to a possible sub-object that
70 has a virtual table pointer in it that is the vtable parent for
74 build_headof_sub (exp
)
77 tree type
= TREE_TYPE (TREE_TYPE (exp
));
78 tree basetype
= CLASSTYPE_RTTI (type
);
79 tree binfo
= get_binfo (basetype
, type
, 0);
81 exp
= convert_pointer_to_real (binfo
, exp
);
85 /* Given the expression EXP of type `class *', return the head of the
86 object pointed to by EXP with type cv void*, if the class has any
87 virtual functions (TYPE_VIRTUAL_P), else just return the
94 tree type
= TREE_TYPE (exp
);
98 if (TREE_CODE (type
) != POINTER_TYPE
)
100 error ("`headof' applied to non-pointer type");
101 return error_mark_node
;
103 type
= TREE_TYPE (type
);
105 if (!TYPE_VIRTUAL_P (type
))
107 if (CLASSTYPE_COM_INTERFACE (type
))
109 cp_error ("RTTI not supported for COM interface type `%T'", type
);
110 return error_mark_node
;
113 /* If we don't have rtti stuff, get to a sub-object that does. */
114 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp
))))
115 exp
= build_headof_sub (exp
);
117 /* We use this a couple of times below, protect it. */
118 exp
= save_expr (exp
);
120 aref
= build_vtbl_ref (build_indirect_ref (exp
, NULL_PTR
), integer_zero_node
);
122 if (flag_vtable_thunks
)
125 offset
= build_component_ref (aref
, delta_identifier
, NULL_TREE
, 0);
127 type
= build_qualified_type (ptr_type_node
,
128 CP_TYPE_QUALS (TREE_TYPE (exp
)));
129 return build (PLUS_EXPR
, type
, exp
,
130 cp_convert (ptrdiff_type_node
, offset
));
133 /* Build a call to a generic entry point taking and returning void. */
139 tree d
= get_identifier (name
);
142 if (IDENTIFIER_GLOBAL_VALUE (d
))
143 d
= IDENTIFIER_GLOBAL_VALUE (d
);
146 push_obstacks (&permanent_obstack
, &permanent_obstack
);
148 type
= build_function_type (void_type_node
, void_list_node
);
149 d
= build_lang_decl (FUNCTION_DECL
, d
, type
);
150 DECL_EXTERNAL (d
) = 1;
152 DECL_ARTIFICIAL (d
) = 1;
153 pushdecl_top_level (d
);
154 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 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 (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
208 cp_error ("taking typeid of incomplete type `%T'", type
);
209 return error_mark_node
;
212 /* If exp is a reference to polymorphic type, get the real type_info. */
213 if (TYPE_VIRTUAL_P (type
) && ! resolves_to_fixed_type_p (exp
, 0))
215 /* build reference to type_info from vtable. */
219 error ("taking dynamic typeid of object with -fno-rtti");
220 if (CLASSTYPE_COM_INTERFACE (type
))
222 cp_error ("RTTI not supported for COM interface type `%T'", type
);
223 return error_mark_node
;
226 /* If we don't have rtti stuff, get to a sub-object that does. */
227 if (! CLASSTYPE_VFIELDS (type
))
229 exp
= build_unary_op (ADDR_EXPR
, exp
, 0);
230 exp
= build_headof_sub (exp
);
231 exp
= build_indirect_ref (exp
, NULL_PTR
);
234 if (flag_vtable_thunks
)
235 t
= build_vfn_ref ((tree
*) 0, exp
, integer_one_node
);
237 t
= build_vfn_ref ((tree
*) 0, exp
, integer_zero_node
);
238 TREE_TYPE (t
) = build_pointer_type (tinfo_fn_type
);
242 /* otherwise return the type_info for the static type of the expr. */
243 return get_tinfo_fn (TYPE_MAIN_VARIANT (type
));
250 exp
= get_tinfo_fn_dynamic (exp
);
251 exp
= build_call (exp
, TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
252 return convert_from_reference (exp
);
259 tree cond
= NULL_TREE
;
265 error ("cannot use typeid with -fno-rtti");
266 return error_mark_node
;
269 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
271 error ("must #include <typeinfo> before using typeid");
272 return error_mark_node
;
275 if (processing_template_decl
)
276 return build_min_nt (TYPEID_EXPR
, exp
);
278 if (TREE_CODE (exp
) == INDIRECT_REF
279 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp
, 0))) == POINTER_TYPE
280 && TYPE_VIRTUAL_P (TREE_TYPE (exp
))
281 && ! resolves_to_fixed_type_p (exp
, &nonnull
)
284 exp
= stabilize_reference (exp
);
285 cond
= cp_convert (boolean_type_node
, TREE_OPERAND (exp
, 0));
288 exp
= get_tinfo_fn_dynamic (exp
);
290 if (exp
== error_mark_node
)
291 return error_mark_node
;
293 type
= TREE_TYPE (tinfo_fn_type
);
294 exp
= build_call (exp
, type
, NULL_TREE
);
298 tree bad
= throw_bad_typeid ();
300 bad
= build_compound_expr
301 (tree_cons (NULL_TREE
, bad
, build_expr_list
302 (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
303 exp
= build (COND_EXPR
, type
, cond
, exp
, bad
);
306 return convert_from_reference (exp
);
313 tree tname
= build_overload_with_type (get_identifier ("__ti"), type
);
317 if (IDENTIFIER_GLOBAL_VALUE (tname
))
318 return IDENTIFIER_GLOBAL_VALUE (tname
);
320 /* Figure out how much space we need to allocate for the type_info object.
321 If our struct layout or the type_info classes are changed, this will
322 need to be modified. */
323 if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
324 size
= 3 * POINTER_SIZE
+ INT_TYPE_SIZE
;
325 else if (TREE_CODE (type
) == POINTER_TYPE
326 && ! (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
327 || TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
))
328 size
= 3 * POINTER_SIZE
;
329 else if (IS_AGGR_TYPE (type
))
331 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
332 size
= 2 * POINTER_SIZE
;
333 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
335 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
336 size
= 3 * POINTER_SIZE
;
338 size
= 3 * POINTER_SIZE
+ TYPE_PRECISION (sizetype
);
341 size
= 2 * POINTER_SIZE
;
343 push_obstacks (&permanent_obstack
, &permanent_obstack
);
345 /* The type for a character array of the appropriate size. */
346 arrtype
= build_cplus_array_type
347 (unsigned_char_type_node
,
348 build_index_type (size_int (size
/ BITS_PER_UNIT
- 1)));
350 tdecl
= build_decl (VAR_DECL
, tname
, arrtype
);
351 TREE_PUBLIC (tdecl
) = 1;
352 DECL_EXTERNAL (tdecl
) = 1;
353 DECL_ARTIFICIAL (tdecl
) = 1;
354 push_to_top_level ();
356 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
357 pop_from_top_level ();
371 if (TREE_CODE (type
) == OFFSET_TYPE
)
372 type
= TREE_TYPE (type
);
373 if (TREE_CODE (type
) == METHOD_TYPE
)
374 type
= build_function_type (TREE_TYPE (type
),
375 TREE_CHAIN (TYPE_ARG_TYPES (type
)));
377 name
= build_overload_with_type (tinfo_fn_id
, type
);
379 if (IDENTIFIER_GLOBAL_VALUE (name
))
380 return IDENTIFIER_GLOBAL_VALUE (name
);
382 push_obstacks (&permanent_obstack
, &permanent_obstack
);
384 d
= build_lang_decl (FUNCTION_DECL
, name
, tinfo_fn_type
);
385 DECL_EXTERNAL (d
) = 1;
387 DECL_ARTIFICIAL (d
) = 1;
388 DECL_NOT_REALLY_EXTERN (d
) = 1;
389 SET_DECL_TINFO_FN_P (d
);
390 TREE_TYPE (name
) = type
;
392 pushdecl_top_level (d
);
393 make_function_rtl (d
);
395 mark_inline_for_output (d
);
408 (get_tinfo_fn (type
), TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
409 return convert_from_reference (t
);
412 /* Return the type_info object for TYPE, creating it if necessary. */
418 if (type
== error_mark_node
)
419 return error_mark_node
;
421 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
423 error ("must #include <typeinfo> before using typeid");
424 return error_mark_node
;
428 error ("requesting typeid with -fno-rtti");
430 if (processing_template_decl
)
431 return build_min_nt (TYPEID_EXPR
, type
);
433 /* If the type of the type-id is a reference type, the result of the
434 typeid expression refers to a type_info object representing the
436 if (TREE_CODE (type
) == REFERENCE_TYPE
)
437 type
= TREE_TYPE (type
);
439 /* The top-level cv-qualifiers of the lvalue expression or the type-id
440 that is the operand of typeid are always ignored. */
441 type
= TYPE_MAIN_VARIANT (type
);
443 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
445 cp_error ("taking typeid of incomplete type `%T'", type
);
446 return error_mark_node
;
449 return get_typeid_1 (type
);
452 /* Check whether TEST is null before returning RESULT. If TEST is used in
453 RESULT, it must have previously had a save_expr applied to it. */
456 ifnonnull (test
, result
)
459 return build (COND_EXPR
, TREE_TYPE (result
),
460 build (EQ_EXPR
, boolean_type_node
, test
, integer_zero_node
),
461 cp_convert (TREE_TYPE (result
), integer_zero_node
),
465 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
469 build_dynamic_cast_1 (type
, expr
)
472 enum tree_code tc
= TREE_CODE (type
);
476 tree old_expr
= expr
;
478 if (TREE_CODE (expr
) == OFFSET_REF
)
479 expr
= resolve_offset_ref (expr
);
481 exprtype
= TREE_TYPE (expr
);
482 assert (exprtype
!= NULL_TREE
);
483 ec
= TREE_CODE (exprtype
);
488 if (ec
== REFERENCE_TYPE
)
490 expr
= convert_from_reference (expr
);
491 exprtype
= TREE_TYPE (expr
);
492 ec
= TREE_CODE (exprtype
);
494 if (ec
!= POINTER_TYPE
)
496 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
498 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
500 if (!at_least_as_qualified_p (TREE_TYPE (type
),
501 TREE_TYPE (exprtype
)))
503 if (TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
505 /* else fall through */
507 if (TREE_CODE (TREE_TYPE (type
)) != RECORD_TYPE
)
509 if (TYPE_SIZE (complete_type (TREE_TYPE (type
))) == NULL_TREE
)
512 /* else fall through */
517 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
518 if (ec
== RECORD_TYPE
)
520 exprtype
= build_reference_type (exprtype
);
521 expr
= convert_to_reference (exprtype
, expr
, CONV_IMPLICIT
,
522 LOOKUP_NORMAL
, NULL_TREE
);
526 if (tc
== REFERENCE_TYPE
)
528 if (ec
!= REFERENCE_TYPE
)
530 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
532 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
534 if (!at_least_as_qualified_p (TREE_TYPE (type
),
535 TREE_TYPE (exprtype
)))
539 /* If *type is an unambiguous accessible base class of *exprtype,
540 convert statically. */
545 distance
= get_base_distance (TREE_TYPE (type
), TREE_TYPE (exprtype
), 1,
550 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
551 TREE_TYPE (exprtype
), TREE_TYPE (type
));
552 return error_mark_node
;
556 cp_error ("dynamic_cast from `%T' to private base class `%T'",
557 TREE_TYPE (exprtype
), TREE_TYPE (type
));
558 return error_mark_node
;
562 return build_vbase_path (PLUS_EXPR
, type
, expr
, path
, 0);
565 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
566 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype
)))
569 /* if TYPE is `void *', return pointer to complete object. */
570 if (tc
== POINTER_TYPE
571 && TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
573 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
574 if (TREE_CODE (expr
) == ADDR_EXPR
575 && TREE_CODE (TREE_OPERAND (expr
, 0)) == VAR_DECL
576 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == RECORD_TYPE
)
577 return build1 (NOP_EXPR
, type
, expr
);
579 /* Since expr is used twice below, save it. */
580 expr
= save_expr (expr
);
582 expr1
= build_headof (expr
);
583 if (TREE_TYPE (expr1
) != type
)
584 expr1
= build1 (NOP_EXPR
, type
, expr1
);
585 return ifnonnull (expr
, expr1
);
590 tree result
, td1
, td2
, td3
, elems
, expr2
;
592 /* If we got here, we can't convert statically. Therefore,
593 dynamic_cast<D&>(b) (b an object) cannot succeed. */
594 if (ec
== REFERENCE_TYPE
)
596 if (TREE_CODE (old_expr
) == VAR_DECL
597 && TREE_CODE (TREE_TYPE (old_expr
)) == RECORD_TYPE
)
599 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
601 return throw_bad_cast ();
604 /* Ditto for dynamic_cast<D*>(&b). */
605 else if (TREE_CODE (expr
) == ADDR_EXPR
)
607 tree op
= TREE_OPERAND (expr
, 0);
608 if (TREE_CODE (op
) == VAR_DECL
609 && TREE_CODE (TREE_TYPE (op
)) == RECORD_TYPE
)
611 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
613 retval
= build_int_2 (0, 0);
614 TREE_TYPE (retval
) = type
;
619 /* Since expr is used twice below, save it. */
620 expr
= save_expr (expr
);
623 if (tc
== REFERENCE_TYPE
)
624 expr1
= build_unary_op (ADDR_EXPR
, expr1
, 0);
626 /* Build run-time conversion. */
627 expr2
= build_headof (expr1
);
629 if (ec
== POINTER_TYPE
)
630 td1
= get_tinfo_fn_dynamic (build_indirect_ref (expr
, NULL_PTR
));
632 td1
= get_tinfo_fn_dynamic (expr
);
633 td1
= decay_conversion (td1
);
635 td2
= decay_conversion
636 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type
))));
637 td3
= decay_conversion
638 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype
))));
641 (NULL_TREE
, td1
, tree_cons
642 (NULL_TREE
, td2
, tree_cons
643 (NULL_TREE
, build_int_2 (1, 0), tree_cons
644 (NULL_TREE
, expr2
, tree_cons
645 (NULL_TREE
, td3
, tree_cons
646 (NULL_TREE
, expr1
, NULL_TREE
))))));
648 dcast_fn
= get_identifier ("__dynamic_cast");
649 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn
))
650 dcast_fn
= IDENTIFIER_GLOBAL_VALUE (dcast_fn
);
655 push_obstacks (&permanent_obstack
, &permanent_obstack
);
657 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
658 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
659 (NULL_TREE
, integer_type_node
, tree_cons
660 (NULL_TREE
, ptr_type_node
, tree_cons
661 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
662 (NULL_TREE
, ptr_type_node
, void_list_node
))))));
663 tmp
= build_function_type (ptr_type_node
, tmp
);
664 dcast_fn
= build_lang_decl (FUNCTION_DECL
, dcast_fn
, tmp
);
665 DECL_EXTERNAL (dcast_fn
) = 1;
666 TREE_PUBLIC (dcast_fn
) = 1;
667 DECL_ARTIFICIAL (dcast_fn
) = 1;
668 pushdecl_top_level (dcast_fn
);
669 make_function_rtl (dcast_fn
);
673 mark_used (dcast_fn
);
675 (dcast_fn
, TREE_TYPE (TREE_TYPE (dcast_fn
)), elems
);
677 if (tc
== REFERENCE_TYPE
)
679 expr1
= throw_bad_cast ();
680 expr1
= build_compound_expr
681 (tree_cons (NULL_TREE
, expr1
,
682 build_expr_list (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
683 TREE_TYPE (expr1
) = type
;
684 result
= save_expr (result
);
685 return build (COND_EXPR
, type
, result
, result
, expr1
);
688 /* Now back to the type we want from a void*. */
689 result
= cp_convert (type
, result
);
690 return ifnonnull (expr
, result
);
695 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
696 expr
, exprtype
, type
);
697 return error_mark_node
;
701 build_dynamic_cast (type
, expr
)
704 if (type
== error_mark_node
|| expr
== error_mark_node
)
705 return error_mark_node
;
707 if (processing_template_decl
)
708 return build_min (DYNAMIC_CAST_EXPR
, type
, expr
);
710 return convert_from_reference (build_dynamic_cast_1 (type
, expr
));
713 /* Build and initialize various sorts of descriptors. Every descriptor
714 node has a name associated with it (the name created by mangling).
715 For this reason, we use the identifier as our access to the __*_desc
716 nodes, instead of sticking them directly in the types. Otherwise we
717 would burden all built-in types (and pointer types) with slots that
718 we don't necessarily want to use.
720 For each descriptor we build, we build a variable that contains
721 the descriptor's information. When we need this info at runtime,
722 all we need is access to these variables.
724 Note: these constructors always return the address of the descriptor
725 info, since that is simplest for their mutual interaction. */
727 /* Build an initializer for a __si_type_info node. */
730 expand_si_desc (tdecl
, type
)
735 const char *name
= build_overload_name (type
, 1, 1);
736 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
738 type
= BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0));
739 finish_expr_stmt (get_typeid_1 (type
));
740 t
= decay_conversion (get_tinfo_var (type
));
742 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
743 (NULL_TREE
, decay_conversion (name_string
), tree_cons
744 (NULL_TREE
, t
, NULL_TREE
)));
746 fn
= get_identifier ("__rtti_si");
747 if (IDENTIFIER_GLOBAL_VALUE (fn
))
748 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
752 push_obstacks (&permanent_obstack
, &permanent_obstack
);
754 (NULL_TREE
, ptr_type_node
, tree_cons
755 (NULL_TREE
, const_string_type_node
, tree_cons
756 (NULL_TREE
, build_pointer_type (type_info_type_node
),
758 tmp
= build_function_type (void_type_node
, tmp
);
760 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
761 DECL_EXTERNAL (fn
) = 1;
762 TREE_PUBLIC (fn
) = 1;
763 DECL_ARTIFICIAL (fn
) = 1;
764 pushdecl_top_level (fn
);
765 make_function_rtl (fn
);
770 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
771 finish_expr_stmt (fn
);
774 /* Build an initializer for a __class_type_info node. */
777 expand_class_desc (tdecl
, type
)
785 int i
= CLASSTYPE_N_BASECLASSES (type
);
787 tree binfos
= TYPE_BINFO_BASETYPES (type
);
789 /* See code below that used these. */
790 tree vb
= CLASSTYPE_VBASECLASSES (type
);
793 tree base
, elems
, access
, offset
, isvir
;
794 tree elt
, elts
= NULL_TREE
;
795 static tree base_info_type_node
;
797 if (base_info_type_node
== NULL_TREE
)
801 /* A reasonably close approximation of __class_type_info::base_info */
803 push_obstacks (&permanent_obstack
, &permanent_obstack
);
804 base_info_type_node
= make_lang_type (RECORD_TYPE
);
806 /* Actually const __user_type_info * */
807 fields
[0] = build_lang_decl
808 (FIELD_DECL
, NULL_TREE
,
809 build_pointer_type (build_qualified_type
810 (type_info_type_node
,
812 fields
[1] = build_lang_decl
813 (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
814 DECL_BIT_FIELD (fields
[1]) = 1;
815 DECL_FIELD_SIZE (fields
[1]) = 29;
817 fields
[2] = build_lang_decl
818 (FIELD_DECL
, NULL_TREE
, boolean_type_node
);
819 DECL_BIT_FIELD (fields
[2]) = 1;
820 DECL_FIELD_SIZE (fields
[2]) = 1;
822 /* Actually enum access */
823 fields
[3] = build_lang_decl
824 (FIELD_DECL
, NULL_TREE
, integer_type_node
);
825 DECL_BIT_FIELD (fields
[3]) = 1;
826 DECL_FIELD_SIZE (fields
[3]) = 2;
828 finish_builtin_type (base_info_type_node
, "__base_info", fields
,
835 tree binfo
= TREE_VEC_ELT (binfos
, i
);
837 finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo
)));
838 base
= decay_conversion (get_tinfo_var (BINFO_TYPE (binfo
)));
840 if (TREE_VIA_VIRTUAL (binfo
))
842 tree t
= BINFO_TYPE (binfo
);
846 FORMAT_VBASE_NAME (name
, t
);
847 field
= lookup_field (type
, get_identifier (name
), 0, 0);
848 offset
= size_binop (FLOOR_DIV_EXPR
,
849 DECL_FIELD_BITPOS (field
), size_int (BITS_PER_UNIT
));
850 offset
= convert (sizetype
, offset
);
853 offset
= BINFO_OFFSET (binfo
);
855 if (TREE_VIA_PUBLIC (binfo
))
856 access
= access_public_node
;
857 else if (TREE_VIA_PROTECTED (binfo
))
858 access
= access_protected_node
;
860 access
= access_private_node
;
861 if (TREE_VIA_VIRTUAL (binfo
))
862 isvir
= boolean_true_node
;
864 isvir
= boolean_false_node
;
867 (CONSTRUCTOR
, base_info_type_node
, NULL_TREE
, tree_cons
868 (NULL_TREE
, base
, tree_cons
869 (NULL_TREE
, offset
, tree_cons
870 (NULL_TREE
, isvir
, tree_cons
871 (NULL_TREE
, access
, NULL_TREE
)))));
872 TREE_HAS_CONSTRUCTOR (elt
) = TREE_CONSTANT (elt
) = TREE_STATIC (elt
) = 1;
873 elts
= tree_cons (NULL_TREE
, elt
, elts
);
881 access
= access_public_node
;
884 b
= TREE_VEC_ELT (binfos
, i
);
885 if (BINFO_TYPE (vb
) == BINFO_TYPE (b
) && TREE_VIA_VIRTUAL (b
))
887 if (TREE_VIA_PUBLIC (b
))
888 access
= access_public_node
;
889 else if (TREE_VIA_PROTECTED (b
))
890 access
= access_protected_node
;
892 access
= access_private_node
;
896 base
= build_t_desc (BINFO_TYPE (vb
), 1);
897 offset
= BINFO_OFFSET (vb
);
898 isvir
= build_int_2 (1, 0);
900 base_list
= tree_cons (NULL_TREE
, base
, base_list
);
901 isvir_list
= tree_cons (NULL_TREE
, isvir
, isvir_list
);
902 acc_list
= tree_cons (NULL_TREE
, access
, acc_list
);
903 off_list
= tree_cons (NULL_TREE
, offset
, off_list
);
906 vb
= TREE_CHAIN (vb
);
910 name
= build_overload_name (type
, 1, 1);
911 name_string
= combine_strings (build_string (strlen (name
)+1, name
));
914 tree arrtype
= build_array_type (base_info_type_node
, NULL_TREE
);
915 elts
= build (CONSTRUCTOR
, arrtype
, NULL_TREE
, elts
);
916 TREE_HAS_CONSTRUCTOR (elts
) = TREE_CONSTANT (elts
)
917 = TREE_STATIC (elts
) = 1;
918 complete_array_type (arrtype
, elts
, 1);
922 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
923 (NULL_TREE
, decay_conversion (name_string
), tree_cons
924 (NULL_TREE
, decay_conversion (elts
), tree_cons
925 (NULL_TREE
, cp_convert (sizetype
, build_int_2 (base_cnt
, 0)),
928 fn
= get_identifier ("__rtti_class");
929 if (IDENTIFIER_GLOBAL_VALUE (fn
))
930 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 (base_info_type_node
), tree_cons
938 (NULL_TREE
, sizetype
, void_list_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
);
951 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
952 finish_expr_stmt (fn
);
955 /* Build an initializer for a __pointer_type_info node. */
958 expand_ptr_desc (tdecl
, type
)
963 const char *name
= build_overload_name (type
, 1, 1);
964 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
966 type
= TREE_TYPE (type
);
967 finish_expr_stmt (get_typeid_1 (type
));
968 t
= decay_conversion (get_tinfo_var (type
));
970 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
971 (NULL_TREE
, decay_conversion (name_string
), tree_cons
972 (NULL_TREE
, t
, NULL_TREE
)));
974 fn
= get_identifier ("__rtti_ptr");
975 if (IDENTIFIER_GLOBAL_VALUE (fn
))
976 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
980 push_obstacks (&permanent_obstack
, &permanent_obstack
);
982 (NULL_TREE
, ptr_type_node
, tree_cons
983 (NULL_TREE
, const_string_type_node
, tree_cons
984 (NULL_TREE
, build_pointer_type (type_info_type_node
),
986 tmp
= build_function_type (void_type_node
, tmp
);
988 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
989 DECL_EXTERNAL (fn
) = 1;
990 TREE_PUBLIC (fn
) = 1;
991 DECL_ARTIFICIAL (fn
) = 1;
992 pushdecl_top_level (fn
);
993 make_function_rtl (fn
);
998 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
999 finish_expr_stmt (fn
);
1002 /* Build an initializer for a __attr_type_info node. */
1005 expand_attr_desc (tdecl
, type
)
1010 const char *name
= build_overload_name (type
, 1, 1);
1011 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1012 tree attrval
= build_int_2 (TYPE_QUALS (type
), 0);
1014 finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type
)));
1015 t
= decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type
)));
1017 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1018 (NULL_TREE
, decay_conversion (name_string
), tree_cons
1019 (NULL_TREE
, attrval
, tree_cons (NULL_TREE
, t
, NULL_TREE
))));
1021 fn
= get_identifier ("__rtti_attr");
1022 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1023 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1027 push_obstacks (&permanent_obstack
, &permanent_obstack
);
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
);
1046 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1047 finish_expr_stmt (fn
);
1050 /* Build an initializer for a type_info node that just has a name. */
1053 expand_generic_desc (tdecl
, type
, fnname
)
1058 const char *name
= build_overload_name (type
, 1, 1);
1059 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1060 tree elems
= tree_cons
1061 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1062 (NULL_TREE
, decay_conversion (name_string
), NULL_TREE
));
1064 tree fn
= get_identifier (fnname
);
1065 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1066 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1070 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1072 (NULL_TREE
, ptr_type_node
, tree_cons
1073 (NULL_TREE
, const_string_type_node
, void_list_node
));
1074 tmp
= build_function_type (void_type_node
, tmp
);
1076 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1077 DECL_EXTERNAL (fn
) = 1;
1078 TREE_PUBLIC (fn
) = 1;
1079 DECL_ARTIFICIAL (fn
) = 1;
1080 pushdecl_top_level (fn
);
1081 make_function_rtl (fn
);
1086 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1087 finish_expr_stmt (fn
);
1090 /* Generate the code for a type_info initialization function.
1091 Note that we take advantage of the passage
1093 5.2.7 Type identification [expr.typeid]
1095 Whether or not the destructor is called for the type_info object at the
1096 end of the program is unspecified.
1098 and don't bother to arrange for these objects to be destroyed. It
1099 doesn't matter, anyway, since the destructors don't do anything.
1101 This must only be called from toplevel (i.e. from finish_file)! */
1104 synthesize_tinfo_fn (fndecl
)
1107 tree type
= TREE_TYPE (DECL_NAME (fndecl
));
1108 tree tmp
, addr
, tdecl
;
1115 import_export_decl (fndecl
);
1116 if (DECL_REALLY_EXTERN (fndecl
))
1120 /* Declare the static typeinfo variable. */
1121 tdecl
= get_tinfo_var (type
);
1122 DECL_EXTERNAL (tdecl
) = 0;
1123 TREE_STATIC (tdecl
) = 1;
1124 DECL_COMMON (tdecl
) = 1;
1125 TREE_USED (tdecl
) = 1;
1126 DECL_ALIGN (tdecl
) = TYPE_ALIGN (ptr_type_node
);
1127 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
1129 /* Begin processing the function. */
1130 start_function (NULL_TREE
, fndecl
, NULL_TREE
,
1131 SF_DEFAULT
| SF_PRE_PARSED
);
1132 store_parm_decls ();
1135 /* Begin the body of the function. */
1136 compound_stmt
= begin_compound_stmt (/*has_no_scope=*/0);
1138 /* For convenience, we save away the address of the static
1139 variable. Since we will process expression-statements between
1140 here and the end of the function, we must call push_momentary to
1141 keep ADDR from being overwritten. */
1142 addr
= decay_conversion (tdecl
);
1145 /* If the first word of the array (the vtable) is non-zero, we've already
1146 initialized the object, so don't do it again. */
1147 if_stmt
= begin_if_stmt ();
1148 tmp
= cp_convert (build_pointer_type (ptr_type_node
), addr
);
1149 tmp
= build_indirect_ref (tmp
, 0);
1150 tmp
= build_binary_op (EQ_EXPR
, tmp
, integer_zero_node
);
1151 finish_if_stmt_cond (tmp
, if_stmt
);
1152 then_clause
= begin_compound_stmt (/*has_no_scope=*/0);
1154 if (TREE_CODE (type
) == FUNCTION_TYPE
)
1155 expand_generic_desc (tdecl
, type
, "__rtti_func");
1156 else if (TREE_CODE (type
) == ARRAY_TYPE
)
1157 expand_generic_desc (tdecl
, type
, "__rtti_array");
1158 else if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
1159 expand_attr_desc (tdecl
, type
);
1160 else if (TREE_CODE (type
) == POINTER_TYPE
)
1162 if (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
)
1163 expand_generic_desc (tdecl
, type
, "__rtti_ptmd");
1164 else if (TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
)
1165 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1167 expand_ptr_desc (tdecl
, type
);
1169 else if (TYPE_PTRMEMFUNC_P (type
))
1170 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1171 else if (IS_AGGR_TYPE (type
))
1173 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
1174 expand_generic_desc (tdecl
, type
, "__rtti_user");
1175 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
1177 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
1178 expand_si_desc (tdecl
, type
);
1180 expand_class_desc (tdecl
, type
);
1182 else if (TREE_CODE (type
) == ENUMERAL_TYPE
)
1183 expand_generic_desc (tdecl
, type
, "__rtti_user");
1185 my_friendly_abort (252);
1187 finish_compound_stmt (/*has_no_scope=*/0, then_clause
);
1188 finish_then_clause (if_stmt
);
1191 /* OK, now return the type_info object. */
1192 tmp
= cp_convert (build_pointer_type (type_info_type_node
), addr
);
1193 tmp
= build_indirect_ref (tmp
, 0);
1194 finish_return_stmt (tmp
);
1195 /* Undo the call to push_momentary above. */
1197 /* Finish the function body. */
1198 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt
);
1199 finish_function (lineno
, 0);