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
;
427 if (processing_template_decl
)
428 return build_min_nt (TYPEID_EXPR
, type
);
430 /* If the type of the type-id is a reference type, the result of the
431 typeid expression refers to a type_info object representing the
433 if (TREE_CODE (type
) == REFERENCE_TYPE
)
434 type
= TREE_TYPE (type
);
436 /* The top-level cv-qualifiers of the lvalue expression or the type-id
437 that is the operand of typeid are always ignored. */
438 type
= TYPE_MAIN_VARIANT (type
);
440 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
442 cp_error ("taking typeid of incomplete type `%T'", type
);
443 return error_mark_node
;
446 return get_typeid_1 (type
);
449 /* Check whether TEST is null before returning RESULT. If TEST is used in
450 RESULT, it must have previously had a save_expr applied to it. */
453 ifnonnull (test
, result
)
456 return build (COND_EXPR
, TREE_TYPE (result
),
457 build (EQ_EXPR
, boolean_type_node
, test
, integer_zero_node
),
458 cp_convert (TREE_TYPE (result
), integer_zero_node
),
462 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
466 build_dynamic_cast_1 (type
, expr
)
469 enum tree_code tc
= TREE_CODE (type
);
473 tree old_expr
= expr
;
475 if (TREE_CODE (expr
) == OFFSET_REF
)
476 expr
= resolve_offset_ref (expr
);
478 exprtype
= TREE_TYPE (expr
);
479 assert (exprtype
!= NULL_TREE
);
480 ec
= TREE_CODE (exprtype
);
485 if (ec
== REFERENCE_TYPE
)
487 expr
= convert_from_reference (expr
);
488 exprtype
= TREE_TYPE (expr
);
489 ec
= TREE_CODE (exprtype
);
491 if (ec
!= POINTER_TYPE
)
493 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
495 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
497 if (!at_least_as_qualified_p (TREE_TYPE (type
),
498 TREE_TYPE (exprtype
)))
500 if (TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
502 /* else fall through */
504 if (TREE_CODE (TREE_TYPE (type
)) != RECORD_TYPE
)
506 if (TYPE_SIZE (complete_type (TREE_TYPE (type
))) == NULL_TREE
)
509 /* else fall through */
514 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
515 if (ec
== RECORD_TYPE
)
517 exprtype
= build_reference_type (exprtype
);
518 expr
= convert_to_reference (exprtype
, expr
, CONV_IMPLICIT
,
519 LOOKUP_NORMAL
, NULL_TREE
);
523 if (tc
== REFERENCE_TYPE
)
525 if (ec
!= REFERENCE_TYPE
)
527 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
529 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
531 if (!at_least_as_qualified_p (TREE_TYPE (type
),
532 TREE_TYPE (exprtype
)))
536 /* If *type is an unambiguous accessible base class of *exprtype,
537 convert statically. */
542 distance
= get_base_distance (TREE_TYPE (type
), TREE_TYPE (exprtype
), 1,
547 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
548 TREE_TYPE (exprtype
), TREE_TYPE (type
));
549 return error_mark_node
;
553 cp_error ("dynamic_cast from `%T' to private base class `%T'",
554 TREE_TYPE (exprtype
), TREE_TYPE (type
));
555 return error_mark_node
;
559 return build_vbase_path (PLUS_EXPR
, type
, expr
, path
, 0);
562 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
563 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype
)))
566 /* if TYPE is `void *', return pointer to complete object. */
567 if (tc
== POINTER_TYPE
568 && TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
570 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
571 if (TREE_CODE (expr
) == ADDR_EXPR
572 && TREE_CODE (TREE_OPERAND (expr
, 0)) == VAR_DECL
573 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == RECORD_TYPE
)
574 return build1 (NOP_EXPR
, type
, expr
);
576 /* Since expr is used twice below, save it. */
577 expr
= save_expr (expr
);
579 expr1
= build_headof (expr
);
580 if (TREE_TYPE (expr1
) != type
)
581 expr1
= build1 (NOP_EXPR
, type
, expr1
);
582 return ifnonnull (expr
, expr1
);
587 tree result
, td1
, td2
, td3
, elems
, expr2
;
588 tree static_type
, target_type
, boff
;
590 /* If we got here, we can't convert statically. Therefore,
591 dynamic_cast<D&>(b) (b an object) cannot succeed. */
592 if (ec
== REFERENCE_TYPE
)
594 if (TREE_CODE (old_expr
) == VAR_DECL
595 && TREE_CODE (TREE_TYPE (old_expr
)) == RECORD_TYPE
)
597 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
599 return throw_bad_cast ();
602 /* Ditto for dynamic_cast<D*>(&b). */
603 else if (TREE_CODE (expr
) == ADDR_EXPR
)
605 tree op
= TREE_OPERAND (expr
, 0);
606 if (TREE_CODE (op
) == VAR_DECL
607 && TREE_CODE (TREE_TYPE (op
)) == RECORD_TYPE
)
609 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
611 retval
= build_int_2 (0, 0);
612 TREE_TYPE (retval
) = type
;
617 /* Since expr is used twice below, save it. */
618 expr
= save_expr (expr
);
621 if (tc
== REFERENCE_TYPE
)
622 expr1
= build_unary_op (ADDR_EXPR
, expr1
, 0);
624 /* Build run-time conversion. */
625 expr2
= build_headof (expr1
);
627 if (ec
== POINTER_TYPE
)
628 td1
= get_tinfo_fn_dynamic (build_indirect_ref (expr
, NULL_PTR
));
630 td1
= get_tinfo_fn_dynamic (expr
);
631 td1
= decay_conversion (td1
);
633 target_type
= TYPE_MAIN_VARIANT (TREE_TYPE (type
));
634 static_type
= TYPE_MAIN_VARIANT (TREE_TYPE (exprtype
));
635 td2
= decay_conversion (get_tinfo_fn (target_type
));
636 td3
= decay_conversion (get_tinfo_fn (static_type
));
638 /* Determine how T and V are related. */
639 boff
= get_dynamic_cast_base_type (static_type
, target_type
);
642 (NULL_TREE
, td1
, tree_cons
643 (NULL_TREE
, td2
, tree_cons
644 (NULL_TREE
, boff
, tree_cons
645 (NULL_TREE
, expr2
, tree_cons
646 (NULL_TREE
, td3
, tree_cons
647 (NULL_TREE
, expr1
, NULL_TREE
))))));
649 dcast_fn
= get_identifier ("__dynamic_cast_2");
650 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn
))
651 dcast_fn
= IDENTIFIER_GLOBAL_VALUE (dcast_fn
);
656 push_obstacks (&permanent_obstack
, &permanent_obstack
);
658 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
659 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
660 (NULL_TREE
, integer_type_node
, tree_cons
661 (NULL_TREE
, ptr_type_node
, tree_cons
662 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
663 (NULL_TREE
, ptr_type_node
, void_list_node
))))));
664 tmp
= build_function_type (ptr_type_node
, tmp
);
665 dcast_fn
= build_lang_decl (FUNCTION_DECL
, dcast_fn
, tmp
);
666 DECL_EXTERNAL (dcast_fn
) = 1;
667 TREE_PUBLIC (dcast_fn
) = 1;
668 DECL_ARTIFICIAL (dcast_fn
) = 1;
669 pushdecl_top_level (dcast_fn
);
670 make_function_rtl (dcast_fn
);
674 mark_used (dcast_fn
);
676 (dcast_fn
, TREE_TYPE (TREE_TYPE (dcast_fn
)), elems
);
678 if (tc
== REFERENCE_TYPE
)
680 expr1
= throw_bad_cast ();
681 expr1
= build_compound_expr
682 (tree_cons (NULL_TREE
, expr1
,
683 build_expr_list (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
684 TREE_TYPE (expr1
) = type
;
685 result
= save_expr (result
);
686 return build (COND_EXPR
, type
, result
, result
, expr1
);
689 /* Now back to the type we want from a void*. */
690 result
= cp_convert (type
, result
);
691 return ifnonnull (expr
, result
);
695 cp_error ("dynamic_cast from non-polymorphic type `%#T'", exprtype
);
696 return error_mark_node
;
699 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
700 expr
, exprtype
, type
);
701 return error_mark_node
;
705 build_dynamic_cast (type
, expr
)
708 if (type
== error_mark_node
|| expr
== error_mark_node
)
709 return error_mark_node
;
711 if (processing_template_decl
)
712 return build_min (DYNAMIC_CAST_EXPR
, type
, expr
);
714 return convert_from_reference (build_dynamic_cast_1 (type
, expr
));
717 /* Build and initialize various sorts of descriptors. Every descriptor
718 node has a name associated with it (the name created by mangling).
719 For this reason, we use the identifier as our access to the __*_desc
720 nodes, instead of sticking them directly in the types. Otherwise we
721 would burden all built-in types (and pointer types) with slots that
722 we don't necessarily want to use.
724 For each descriptor we build, we build a variable that contains
725 the descriptor's information. When we need this info at runtime,
726 all we need is access to these variables.
728 Note: these constructors always return the address of the descriptor
729 info, since that is simplest for their mutual interaction. */
731 /* Build an initializer for a __si_type_info node. */
734 expand_si_desc (tdecl
, type
)
739 const char *name
= build_overload_name (type
, 1, 1);
740 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
742 type
= BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0));
743 finish_expr_stmt (get_typeid_1 (type
));
744 t
= decay_conversion (get_tinfo_var (type
));
746 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
747 (NULL_TREE
, decay_conversion (name_string
), tree_cons
748 (NULL_TREE
, t
, NULL_TREE
)));
750 fn
= get_identifier ("__rtti_si");
751 if (IDENTIFIER_GLOBAL_VALUE (fn
))
752 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
756 push_obstacks (&permanent_obstack
, &permanent_obstack
);
758 (NULL_TREE
, ptr_type_node
, tree_cons
759 (NULL_TREE
, const_string_type_node
, tree_cons
760 (NULL_TREE
, build_pointer_type (type_info_type_node
),
762 tmp
= build_function_type (void_type_node
, tmp
);
764 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
765 DECL_EXTERNAL (fn
) = 1;
766 TREE_PUBLIC (fn
) = 1;
767 DECL_ARTIFICIAL (fn
) = 1;
768 pushdecl_top_level (fn
);
769 make_function_rtl (fn
);
774 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
775 finish_expr_stmt (fn
);
778 /* Build an initializer for a __class_type_info node. */
781 expand_class_desc (tdecl
, type
)
789 int i
= CLASSTYPE_N_BASECLASSES (type
);
791 tree binfos
= TYPE_BINFO_BASETYPES (type
);
793 /* See code below that used these. */
794 tree vb
= CLASSTYPE_VBASECLASSES (type
);
797 tree base
, elems
, access
, offset
, isvir
;
798 tree elt
, elts
= NULL_TREE
;
799 static tree base_info_type_node
;
801 if (base_info_type_node
== NULL_TREE
)
805 /* A reasonably close approximation of __class_type_info::base_info */
807 push_obstacks (&permanent_obstack
, &permanent_obstack
);
808 base_info_type_node
= make_lang_type (RECORD_TYPE
);
810 /* Actually const __user_type_info * */
811 fields
[0] = build_lang_decl
812 (FIELD_DECL
, NULL_TREE
,
813 build_pointer_type (build_qualified_type
814 (type_info_type_node
,
816 fields
[1] = build_lang_decl
817 (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
818 DECL_BIT_FIELD (fields
[1]) = 1;
819 DECL_FIELD_SIZE (fields
[1]) = 29;
821 fields
[2] = build_lang_decl
822 (FIELD_DECL
, NULL_TREE
, boolean_type_node
);
823 DECL_BIT_FIELD (fields
[2]) = 1;
824 DECL_FIELD_SIZE (fields
[2]) = 1;
826 /* Actually enum access */
827 fields
[3] = build_lang_decl
828 (FIELD_DECL
, NULL_TREE
, integer_type_node
);
829 DECL_BIT_FIELD (fields
[3]) = 1;
830 DECL_FIELD_SIZE (fields
[3]) = 2;
832 finish_builtin_type (base_info_type_node
, "__base_info", fields
,
839 tree binfo
= TREE_VEC_ELT (binfos
, i
);
841 finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo
)));
842 base
= decay_conversion (get_tinfo_var (BINFO_TYPE (binfo
)));
844 if (TREE_VIA_VIRTUAL (binfo
))
846 tree t
= BINFO_TYPE (binfo
);
850 FORMAT_VBASE_NAME (name
, t
);
851 field
= lookup_field (type
, get_identifier (name
), 0, 0);
852 offset
= size_binop (FLOOR_DIV_EXPR
,
853 DECL_FIELD_BITPOS (field
), size_int (BITS_PER_UNIT
));
854 offset
= convert (sizetype
, offset
);
857 offset
= BINFO_OFFSET (binfo
);
859 if (TREE_VIA_PUBLIC (binfo
))
860 access
= access_public_node
;
861 else if (TREE_VIA_PROTECTED (binfo
))
862 access
= access_protected_node
;
864 access
= access_private_node
;
865 if (TREE_VIA_VIRTUAL (binfo
))
866 isvir
= boolean_true_node
;
868 isvir
= boolean_false_node
;
871 (CONSTRUCTOR
, base_info_type_node
, NULL_TREE
, tree_cons
872 (NULL_TREE
, base
, tree_cons
873 (NULL_TREE
, offset
, tree_cons
874 (NULL_TREE
, isvir
, tree_cons
875 (NULL_TREE
, access
, NULL_TREE
)))));
876 TREE_HAS_CONSTRUCTOR (elt
) = TREE_CONSTANT (elt
) = TREE_STATIC (elt
) = 1;
877 elts
= tree_cons (NULL_TREE
, elt
, elts
);
885 access
= access_public_node
;
888 b
= TREE_VEC_ELT (binfos
, i
);
889 if (BINFO_TYPE (vb
) == BINFO_TYPE (b
) && TREE_VIA_VIRTUAL (b
))
891 if (TREE_VIA_PUBLIC (b
))
892 access
= access_public_node
;
893 else if (TREE_VIA_PROTECTED (b
))
894 access
= access_protected_node
;
896 access
= access_private_node
;
900 base
= build_t_desc (BINFO_TYPE (vb
), 1);
901 offset
= BINFO_OFFSET (vb
);
902 isvir
= build_int_2 (1, 0);
904 base_list
= tree_cons (NULL_TREE
, base
, base_list
);
905 isvir_list
= tree_cons (NULL_TREE
, isvir
, isvir_list
);
906 acc_list
= tree_cons (NULL_TREE
, access
, acc_list
);
907 off_list
= tree_cons (NULL_TREE
, offset
, off_list
);
910 vb
= TREE_CHAIN (vb
);
914 name
= build_overload_name (type
, 1, 1);
915 name_string
= combine_strings (build_string (strlen (name
)+1, name
));
918 tree arrtype
= build_array_type (base_info_type_node
, NULL_TREE
);
919 elts
= build (CONSTRUCTOR
, arrtype
, NULL_TREE
, elts
);
920 TREE_HAS_CONSTRUCTOR (elts
) = TREE_CONSTANT (elts
)
921 = TREE_STATIC (elts
) = 1;
922 complete_array_type (arrtype
, elts
, 1);
926 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
927 (NULL_TREE
, decay_conversion (name_string
), tree_cons
928 (NULL_TREE
, decay_conversion (elts
), tree_cons
929 (NULL_TREE
, cp_convert (sizetype
, build_int_2 (base_cnt
, 0)),
932 fn
= get_identifier ("__rtti_class");
933 if (IDENTIFIER_GLOBAL_VALUE (fn
))
934 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
937 push_obstacks (&permanent_obstack
, &permanent_obstack
);
939 (NULL_TREE
, ptr_type_node
, tree_cons
940 (NULL_TREE
, const_string_type_node
, tree_cons
941 (NULL_TREE
, build_pointer_type (base_info_type_node
), tree_cons
942 (NULL_TREE
, sizetype
, void_list_node
))));
943 tmp
= build_function_type (void_type_node
, tmp
);
945 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
946 DECL_EXTERNAL (fn
) = 1;
947 TREE_PUBLIC (fn
) = 1;
948 DECL_ARTIFICIAL (fn
) = 1;
949 pushdecl_top_level (fn
);
950 make_function_rtl (fn
);
955 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
956 finish_expr_stmt (fn
);
959 /* Build an initializer for a __pointer_type_info node. */
962 expand_ptr_desc (tdecl
, type
)
967 const char *name
= build_overload_name (type
, 1, 1);
968 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
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
);
984 push_obstacks (&permanent_obstack
, &permanent_obstack
);
986 (NULL_TREE
, ptr_type_node
, tree_cons
987 (NULL_TREE
, const_string_type_node
, tree_cons
988 (NULL_TREE
, build_pointer_type (type_info_type_node
),
990 tmp
= build_function_type (void_type_node
, tmp
);
992 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
993 DECL_EXTERNAL (fn
) = 1;
994 TREE_PUBLIC (fn
) = 1;
995 DECL_ARTIFICIAL (fn
) = 1;
996 pushdecl_top_level (fn
);
997 make_function_rtl (fn
);
1002 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1003 finish_expr_stmt (fn
);
1006 /* Build an initializer for a __attr_type_info node. */
1009 expand_attr_desc (tdecl
, type
)
1014 const char *name
= build_overload_name (type
, 1, 1);
1015 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1016 tree attrval
= build_int_2 (TYPE_QUALS (type
), 0);
1018 finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type
)));
1019 t
= decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type
)));
1021 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1022 (NULL_TREE
, decay_conversion (name_string
), tree_cons
1023 (NULL_TREE
, attrval
, tree_cons (NULL_TREE
, t
, NULL_TREE
))));
1025 fn
= get_identifier ("__rtti_attr");
1026 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1027 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1031 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1033 (NULL_TREE
, ptr_type_node
, tree_cons
1034 (NULL_TREE
, const_string_type_node
, tree_cons
1035 (NULL_TREE
, integer_type_node
, tree_cons
1036 (NULL_TREE
, build_pointer_type (type_info_type_node
),
1038 tmp
= build_function_type (void_type_node
, tmp
);
1040 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1041 DECL_EXTERNAL (fn
) = 1;
1042 TREE_PUBLIC (fn
) = 1;
1043 DECL_ARTIFICIAL (fn
) = 1;
1044 pushdecl_top_level (fn
);
1045 make_function_rtl (fn
);
1050 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1051 finish_expr_stmt (fn
);
1054 /* Build an initializer for a type_info node that just has a name. */
1057 expand_generic_desc (tdecl
, type
, fnname
)
1062 const char *name
= build_overload_name (type
, 1, 1);
1063 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1064 tree elems
= tree_cons
1065 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1066 (NULL_TREE
, decay_conversion (name_string
), NULL_TREE
));
1068 tree fn
= get_identifier (fnname
);
1069 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1070 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1074 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1076 (NULL_TREE
, ptr_type_node
, tree_cons
1077 (NULL_TREE
, const_string_type_node
, void_list_node
));
1078 tmp
= build_function_type (void_type_node
, tmp
);
1080 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1081 DECL_EXTERNAL (fn
) = 1;
1082 TREE_PUBLIC (fn
) = 1;
1083 DECL_ARTIFICIAL (fn
) = 1;
1084 pushdecl_top_level (fn
);
1085 make_function_rtl (fn
);
1090 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1091 finish_expr_stmt (fn
);
1094 /* Generate the code for a type_info initialization function.
1095 Note that we take advantage of the passage
1097 5.2.7 Type identification [expr.typeid]
1099 Whether or not the destructor is called for the type_info object at the
1100 end of the program is unspecified.
1102 and don't bother to arrange for these objects to be destroyed. It
1103 doesn't matter, anyway, since the destructors don't do anything.
1105 This must only be called from toplevel (i.e. from finish_file)! */
1108 synthesize_tinfo_fn (fndecl
)
1111 tree type
= TREE_TYPE (DECL_NAME (fndecl
));
1112 tree tmp
, addr
, tdecl
;
1119 import_export_decl (fndecl
);
1120 if (DECL_REALLY_EXTERN (fndecl
))
1124 /* Declare the static typeinfo variable. */
1125 tdecl
= get_tinfo_var (type
);
1126 DECL_EXTERNAL (tdecl
) = 0;
1127 TREE_STATIC (tdecl
) = 1;
1128 DECL_COMMON (tdecl
) = 1;
1129 TREE_USED (tdecl
) = 1;
1130 DECL_ALIGN (tdecl
) = TYPE_ALIGN (ptr_type_node
);
1131 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
1133 /* Begin processing the function. */
1134 start_function (NULL_TREE
, fndecl
, NULL_TREE
,
1135 SF_DEFAULT
| SF_PRE_PARSED
);
1136 DECL_DEFER_OUTPUT (fndecl
) = 1;
1137 store_parm_decls ();
1140 /* Begin the body of the function. */
1141 compound_stmt
= begin_compound_stmt (/*has_no_scope=*/0);
1143 /* For convenience, we save away the address of the static
1145 addr
= decay_conversion (tdecl
);
1147 /* If the first word of the array (the vtable) is non-zero, we've already
1148 initialized the object, so don't do it again. */
1149 if_stmt
= begin_if_stmt ();
1150 tmp
= cp_convert (build_pointer_type (ptr_type_node
), addr
);
1151 tmp
= build_indirect_ref (tmp
, 0);
1152 tmp
= build_binary_op (EQ_EXPR
, tmp
, integer_zero_node
);
1153 finish_if_stmt_cond (tmp
, if_stmt
);
1154 then_clause
= begin_compound_stmt (/*has_no_scope=*/0);
1156 if (TREE_CODE (type
) == FUNCTION_TYPE
)
1157 expand_generic_desc (tdecl
, type
, "__rtti_func");
1158 else if (TREE_CODE (type
) == ARRAY_TYPE
)
1159 expand_generic_desc (tdecl
, type
, "__rtti_array");
1160 else if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
1161 expand_attr_desc (tdecl
, type
);
1162 else if (TREE_CODE (type
) == POINTER_TYPE
)
1164 if (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
)
1165 expand_generic_desc (tdecl
, type
, "__rtti_ptmd");
1166 else if (TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
)
1167 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1169 expand_ptr_desc (tdecl
, type
);
1171 else if (TYPE_PTRMEMFUNC_P (type
))
1172 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1173 else if (IS_AGGR_TYPE (type
))
1175 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
1176 expand_generic_desc (tdecl
, type
, "__rtti_user");
1177 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
1179 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
1180 expand_si_desc (tdecl
, type
);
1182 expand_class_desc (tdecl
, type
);
1184 else if (TREE_CODE (type
) == ENUMERAL_TYPE
)
1185 expand_generic_desc (tdecl
, type
, "__rtti_user");
1187 my_friendly_abort (252);
1189 finish_compound_stmt (/*has_no_scope=*/0, then_clause
);
1190 finish_then_clause (if_stmt
);
1193 /* OK, now return the type_info object. */
1194 tmp
= cp_convert (build_pointer_type (type_info_type_node
), addr
);
1195 tmp
= build_indirect_ref (tmp
, 0);
1196 finish_return_stmt (tmp
);
1197 /* Finish the function body. */
1198 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt
);
1199 expand_body (finish_function (lineno
, 0));