1 /* RunTime Type Identification
2 Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
3 Mostly written by Jason Merrill (jason@cygnus.com).
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
33 #define INT_TYPE_SIZE BITS_PER_WORD
36 extern struct obstack permanent_obstack
;
38 static tree call_void_fn
PROTO((const char *));
39 static tree build_headof_sub
PROTO((tree
));
40 static tree build_headof
PROTO((tree
));
41 static tree get_tinfo_var
PROTO((tree
));
42 static tree ifnonnull
PROTO((tree
, tree
));
43 static tree build_dynamic_cast_1
PROTO((tree
, tree
));
44 static void expand_si_desc
PROTO((tree
, tree
));
45 static void expand_class_desc
PROTO((tree
, tree
));
46 static void expand_attr_desc
PROTO((tree
, tree
));
47 static void expand_ptr_desc
PROTO((tree
, tree
));
48 static void expand_generic_desc
PROTO((tree
, tree
, const char *));
49 static tree throw_bad_cast
PROTO((void));
50 static tree throw_bad_typeid
PROTO((void));
52 tree type_info_type_node
;
57 init_rtti_processing ()
60 push_namespace (get_identifier ("std"));
61 type_info_type_node
= xref_tag
62 (class_type_node
, get_identifier ("type_info"), 1);
65 tinfo_fn_id
= get_identifier ("__tf");
66 tinfo_fn_type
= build_function_type
67 (build_reference_type (build_qualified_type (type_info_type_node
,
72 /* Given a pointer to an object with at least one virtual table
73 pointer somewhere, return a pointer to a possible sub-object that
74 has a virtual table pointer in it that is the vtable parent for
78 build_headof_sub (exp
)
81 tree type
= TREE_TYPE (TREE_TYPE (exp
));
82 tree basetype
= CLASSTYPE_RTTI (type
);
83 tree binfo
= get_binfo (basetype
, type
, 0);
85 exp
= convert_pointer_to_real (binfo
, exp
);
89 /* Given the expression EXP of type `class *', return the head of the
90 object pointed to by EXP with type cv void*, if the class has any
91 virtual functions (TYPE_VIRTUAL_P), else just return the
98 tree type
= TREE_TYPE (exp
);
102 if (TREE_CODE (type
) != POINTER_TYPE
)
104 error ("`headof' applied to non-pointer type");
105 return error_mark_node
;
107 type
= TREE_TYPE (type
);
109 if (!TYPE_VIRTUAL_P (type
))
111 if (CLASSTYPE_COM_INTERFACE (type
))
113 cp_error ("RTTI not supported for COM interface type `%T'", type
);
114 return error_mark_node
;
117 /* If we don't have rtti stuff, get to a sub-object that does. */
118 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp
))))
119 exp
= build_headof_sub (exp
);
121 /* We use this a couple of times below, protect it. */
122 exp
= save_expr (exp
);
124 aref
= build_vtbl_ref (build_indirect_ref (exp
, NULL_PTR
), integer_zero_node
);
126 if (flag_vtable_thunks
)
129 offset
= build_component_ref (aref
, delta_identifier
, NULL_TREE
, 0);
131 type
= build_qualified_type (ptr_type_node
,
132 CP_TYPE_QUALS (TREE_TYPE (exp
)));
133 return build (PLUS_EXPR
, type
, exp
,
134 cp_convert (ptrdiff_type_node
, offset
));
137 /* Build a call to a generic entry point taking and returning void. */
143 tree d
= get_identifier (name
);
146 if (IDENTIFIER_GLOBAL_VALUE (d
))
147 d
= IDENTIFIER_GLOBAL_VALUE (d
);
150 push_obstacks (&permanent_obstack
, &permanent_obstack
);
152 type
= build_function_type (void_type_node
, void_list_node
);
153 d
= build_lang_decl (FUNCTION_DECL
, d
, type
);
154 DECL_EXTERNAL (d
) = 1;
156 DECL_ARTIFICIAL (d
) = 1;
157 pushdecl_top_level (d
);
158 make_function_rtl (d
);
163 return build_call (d
, void_type_node
, NULL_TREE
);
166 /* Get a bad_cast node for the program to throw...
168 See libstdc++/exception.cc for __throw_bad_cast */
173 return call_void_fn ("__throw_bad_cast");
179 return call_void_fn ("__throw_bad_typeid");
182 /* Return the type_info function associated with the expression EXP. If
183 EXP is a reference to a polymorphic class, return the dynamic type;
184 otherwise return the static type of the expression. */
187 get_tinfo_fn_dynamic (exp
)
192 if (exp
== error_mark_node
)
193 return error_mark_node
;
195 if (type_unknown_p (exp
))
197 error ("typeid of overloaded function");
198 return error_mark_node
;
201 type
= TREE_TYPE (exp
);
203 /* peel back references, so they match. */
204 if (TREE_CODE (type
) == REFERENCE_TYPE
)
205 type
= TREE_TYPE (type
);
207 /* Peel off cv qualifiers. */
208 type
= TYPE_MAIN_VARIANT (type
);
210 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
212 cp_error ("taking typeid of incomplete type `%T'", type
);
213 return error_mark_node
;
216 /* If exp is a reference to polymorphic type, get the real type_info. */
217 if (TYPE_VIRTUAL_P (type
) && ! resolves_to_fixed_type_p (exp
, 0))
219 /* build reference to type_info from vtable. */
223 error ("taking dynamic typeid of object with -fno-rtti");
224 if (CLASSTYPE_COM_INTERFACE (type
))
226 cp_error ("RTTI not supported for COM interface type `%T'", type
);
227 return error_mark_node
;
230 /* If we don't have rtti stuff, get to a sub-object that does. */
231 if (! CLASSTYPE_VFIELDS (type
))
233 exp
= build_unary_op (ADDR_EXPR
, exp
, 0);
234 exp
= build_headof_sub (exp
);
235 exp
= build_indirect_ref (exp
, NULL_PTR
);
238 if (flag_vtable_thunks
)
239 t
= build_vfn_ref ((tree
*) 0, exp
, integer_one_node
);
241 t
= build_vfn_ref ((tree
*) 0, exp
, integer_zero_node
);
242 TREE_TYPE (t
) = build_pointer_type (tinfo_fn_type
);
246 /* otherwise return the type_info for the static type of the expr. */
247 return get_tinfo_fn (TYPE_MAIN_VARIANT (type
));
254 exp
= get_tinfo_fn_dynamic (exp
);
255 exp
= build_call (exp
, TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
256 return convert_from_reference (exp
);
263 tree cond
= NULL_TREE
;
264 tree type
= TREE_TYPE (tinfo_fn_type
);
267 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
269 error ("must #include <typeinfo> before using typeid");
270 return error_mark_node
;
273 if (processing_template_decl
)
274 return build_min_nt (TYPEID_EXPR
, exp
);
276 if (TREE_CODE (exp
) == INDIRECT_REF
277 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp
, 0))) == POINTER_TYPE
278 && TYPE_VIRTUAL_P (TREE_TYPE (exp
))
279 && ! resolves_to_fixed_type_p (exp
, &nonnull
)
282 exp
= stabilize_reference (exp
);
283 cond
= cp_convert (boolean_type_node
, TREE_OPERAND (exp
, 0));
286 exp
= get_tinfo_fn_dynamic (exp
);
288 if (exp
== error_mark_node
)
289 return error_mark_node
;
291 exp
= build_call (exp
, type
, NULL_TREE
);
295 tree bad
= throw_bad_typeid ();
297 bad
= build_compound_expr
298 (expr_tree_cons (NULL_TREE
, bad
, build_expr_list
299 (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
300 exp
= build (COND_EXPR
, type
, cond
, exp
, bad
);
303 return convert_from_reference (exp
);
310 tree tname
= build_overload_with_type (get_identifier ("__ti"), type
);
314 if (IDENTIFIER_GLOBAL_VALUE (tname
))
315 return IDENTIFIER_GLOBAL_VALUE (tname
);
317 /* Figure out how much space we need to allocate for the type_info object.
318 If our struct layout or the type_info classes are changed, this will
319 need to be modified. */
320 if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
321 size
= 3 * POINTER_SIZE
+ INT_TYPE_SIZE
;
322 else if (TREE_CODE (type
) == POINTER_TYPE
323 && ! (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
324 || TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
))
325 size
= 3 * POINTER_SIZE
;
326 else if (IS_AGGR_TYPE (type
))
328 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
329 size
= 2 * POINTER_SIZE
;
330 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
332 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
333 size
= 3 * POINTER_SIZE
;
335 size
= 3 * POINTER_SIZE
+ TYPE_PRECISION (sizetype
);
338 size
= 2 * POINTER_SIZE
;
340 push_obstacks (&permanent_obstack
, &permanent_obstack
);
342 /* The type for a character array of the appropriate size. */
343 arrtype
= build_cplus_array_type
344 (unsigned_char_type_node
,
345 build_index_type (size_int (size
/ BITS_PER_UNIT
- 1)));
347 tdecl
= build_decl (VAR_DECL
, tname
, arrtype
);
348 TREE_PUBLIC (tdecl
) = 1;
349 DECL_EXTERNAL (tdecl
) = 1;
350 DECL_ARTIFICIAL (tdecl
) = 1;
351 pushdecl_top_level (tdecl
);
352 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
366 if (TREE_CODE (type
) == OFFSET_TYPE
)
367 type
= TREE_TYPE (type
);
368 if (TREE_CODE (type
) == METHOD_TYPE
)
369 type
= build_function_type (TREE_TYPE (type
),
370 TREE_CHAIN (TYPE_ARG_TYPES (type
)));
372 name
= build_overload_with_type (tinfo_fn_id
, type
);
374 if (IDENTIFIER_GLOBAL_VALUE (name
))
375 return IDENTIFIER_GLOBAL_VALUE (name
);
377 push_obstacks (&permanent_obstack
, &permanent_obstack
);
379 d
= build_lang_decl (FUNCTION_DECL
, name
, tinfo_fn_type
);
380 DECL_EXTERNAL (d
) = 1;
382 DECL_ARTIFICIAL (d
) = 1;
383 DECL_NOT_REALLY_EXTERN (d
) = 1;
384 DECL_MUTABLE_P (d
) = 1;
385 TREE_TYPE (name
) = copy_to_permanent (type
);
387 pushdecl_top_level (d
);
388 make_function_rtl (d
);
390 mark_inline_for_output (d
);
403 (get_tinfo_fn (type
), TREE_TYPE (tinfo_fn_type
), NULL_TREE
);
404 return convert_from_reference (t
);
407 /* Return the type_info object for TYPE, creating it if necessary. */
413 if (type
== error_mark_node
)
414 return error_mark_node
;
416 if (TYPE_SIZE (type_info_type_node
) == NULL_TREE
)
418 error ("must #include <typeinfo> before using typeid");
419 return error_mark_node
;
423 error ("requesting typeid with -fno-rtti");
425 if (processing_template_decl
)
426 return build_min_nt (TYPEID_EXPR
, type
);
428 /* If the type of the type-id is a reference type, the result of the
429 typeid expression refers to a type_info object representing the
431 if (TREE_CODE (type
) == REFERENCE_TYPE
)
432 type
= TREE_TYPE (type
);
434 /* The top-level cv-qualifiers of the lvalue expression or the type-id
435 that is the operand of typeid are always ignored. */
436 type
= TYPE_MAIN_VARIANT (type
);
438 if (TYPE_SIZE (complete_type (type
)) == NULL_TREE
)
440 cp_error ("taking typeid of incomplete type `%T'", type
);
441 return error_mark_node
;
444 return get_typeid_1 (type
);
447 /* Check whether TEST is null before returning RESULT. If TEST is used in
448 RESULT, it must have previously had a save_expr applied to it. */
451 ifnonnull (test
, result
)
454 return build (COND_EXPR
, TREE_TYPE (result
),
455 build (EQ_EXPR
, boolean_type_node
, test
, integer_zero_node
),
456 cp_convert (TREE_TYPE (result
), integer_zero_node
),
460 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
464 build_dynamic_cast_1 (type
, expr
)
467 enum tree_code tc
= TREE_CODE (type
);
471 tree old_expr
= expr
;
473 if (TREE_CODE (expr
) == OFFSET_REF
)
474 expr
= resolve_offset_ref (expr
);
476 exprtype
= TREE_TYPE (expr
);
477 assert (exprtype
!= NULL_TREE
);
478 ec
= TREE_CODE (exprtype
);
483 if (ec
== REFERENCE_TYPE
)
485 expr
= convert_from_reference (expr
);
486 exprtype
= TREE_TYPE (expr
);
487 ec
= TREE_CODE (exprtype
);
489 if (ec
!= POINTER_TYPE
)
491 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
493 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
495 if (!at_least_as_qualified_p (TREE_TYPE (type
),
496 TREE_TYPE (exprtype
)))
498 if (TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
500 /* else fall through */
502 if (TREE_CODE (TREE_TYPE (type
)) != RECORD_TYPE
)
504 if (TYPE_SIZE (complete_type (TREE_TYPE (type
))) == NULL_TREE
)
507 /* else fall through */
512 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
513 if (ec
== RECORD_TYPE
)
515 exprtype
= build_reference_type (exprtype
);
516 expr
= convert_to_reference (exprtype
, expr
, CONV_IMPLICIT
,
517 LOOKUP_NORMAL
, NULL_TREE
);
521 if (tc
== REFERENCE_TYPE
)
523 if (ec
!= REFERENCE_TYPE
)
525 if (TREE_CODE (TREE_TYPE (exprtype
)) != RECORD_TYPE
)
527 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype
))) == NULL_TREE
)
529 if (!at_least_as_qualified_p (TREE_TYPE (type
),
530 TREE_TYPE (exprtype
)))
534 /* If *type is an unambiguous accessible base class of *exprtype,
535 convert statically. */
540 distance
= get_base_distance (TREE_TYPE (type
), TREE_TYPE (exprtype
), 1,
545 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
546 TREE_TYPE (exprtype
), TREE_TYPE (type
));
547 return error_mark_node
;
551 cp_error ("dynamic_cast from `%T' to private base class `%T'",
552 TREE_TYPE (exprtype
), TREE_TYPE (type
));
553 return error_mark_node
;
557 return build_vbase_path (PLUS_EXPR
, type
, expr
, path
, 0);
560 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
561 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype
)))
564 /* if TYPE is `void *', return pointer to complete object. */
565 if (tc
== POINTER_TYPE
566 && TYPE_MAIN_VARIANT (TREE_TYPE (type
)) == void_type_node
)
568 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
569 if (TREE_CODE (expr
) == ADDR_EXPR
570 && TREE_CODE (TREE_OPERAND (expr
, 0)) == VAR_DECL
571 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == RECORD_TYPE
)
572 return build1 (NOP_EXPR
, type
, expr
);
574 /* Since expr is used twice below, save it. */
575 expr
= save_expr (expr
);
577 expr1
= build_headof (expr
);
578 if (TREE_TYPE (expr1
) != type
)
579 expr1
= build1 (NOP_EXPR
, type
, expr1
);
580 return ifnonnull (expr
, expr1
);
585 tree result
, td1
, td2
, td3
, elems
, expr2
;
587 /* If we got here, we can't convert statically. Therefore,
588 dynamic_cast<D&>(b) (b an object) cannot succeed. */
589 if (ec
== REFERENCE_TYPE
)
591 if (TREE_CODE (old_expr
) == VAR_DECL
592 && TREE_CODE (TREE_TYPE (old_expr
)) == RECORD_TYPE
)
594 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
596 return throw_bad_cast ();
599 /* Ditto for dynamic_cast<D*>(&b). */
600 else if (TREE_CODE (expr
) == ADDR_EXPR
)
602 tree op
= TREE_OPERAND (expr
, 0);
603 if (TREE_CODE (op
) == VAR_DECL
604 && TREE_CODE (TREE_TYPE (op
)) == RECORD_TYPE
)
606 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
608 retval
= build_int_2 (0, 0);
609 TREE_TYPE (retval
) = type
;
614 /* Since expr is used twice below, save it. */
615 expr
= save_expr (expr
);
618 if (tc
== REFERENCE_TYPE
)
619 expr1
= build_unary_op (ADDR_EXPR
, expr1
, 0);
621 /* Build run-time conversion. */
622 expr2
= build_headof (expr1
);
624 if (ec
== POINTER_TYPE
)
625 td1
= get_tinfo_fn_dynamic (build_indirect_ref (expr
, NULL_PTR
));
627 td1
= get_tinfo_fn_dynamic (expr
);
628 td1
= decay_conversion (td1
);
630 td2
= decay_conversion
631 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type
))));
632 td3
= decay_conversion
633 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype
))));
636 (NULL_TREE
, td1
, tree_cons
637 (NULL_TREE
, td2
, tree_cons
638 (NULL_TREE
, build_int_2 (1, 0), tree_cons
639 (NULL_TREE
, expr2
, tree_cons
640 (NULL_TREE
, td3
, tree_cons
641 (NULL_TREE
, expr1
, NULL_TREE
))))));
643 dcast_fn
= get_identifier ("__dynamic_cast");
644 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn
))
645 dcast_fn
= IDENTIFIER_GLOBAL_VALUE (dcast_fn
);
650 push_obstacks (&permanent_obstack
, &permanent_obstack
);
652 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
653 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
654 (NULL_TREE
, integer_type_node
, tree_cons
655 (NULL_TREE
, ptr_type_node
, tree_cons
656 (NULL_TREE
, TREE_TYPE (td1
), tree_cons
657 (NULL_TREE
, ptr_type_node
, void_list_node
))))));
658 tmp
= build_function_type (ptr_type_node
, tmp
);
659 dcast_fn
= build_lang_decl (FUNCTION_DECL
, dcast_fn
, tmp
);
660 DECL_EXTERNAL (dcast_fn
) = 1;
661 TREE_PUBLIC (dcast_fn
) = 1;
662 DECL_ARTIFICIAL (dcast_fn
) = 1;
663 pushdecl_top_level (dcast_fn
);
664 make_function_rtl (dcast_fn
);
668 mark_used (dcast_fn
);
670 (dcast_fn
, TREE_TYPE (TREE_TYPE (dcast_fn
)), elems
);
672 if (tc
== REFERENCE_TYPE
)
674 expr1
= throw_bad_cast ();
675 expr1
= build_compound_expr
676 (expr_tree_cons (NULL_TREE
, expr1
,
677 build_expr_list (NULL_TREE
, cp_convert (type
, integer_zero_node
))));
678 TREE_TYPE (expr1
) = type
;
679 result
= save_expr (result
);
680 return build (COND_EXPR
, type
, result
, result
, expr1
);
683 /* Now back to the type we want from a void*. */
684 result
= cp_convert (type
, result
);
685 return ifnonnull (expr
, result
);
690 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
691 expr
, exprtype
, type
);
692 return error_mark_node
;
696 build_dynamic_cast (type
, expr
)
699 if (type
== error_mark_node
|| expr
== error_mark_node
)
700 return error_mark_node
;
702 if (processing_template_decl
)
703 return build_min (DYNAMIC_CAST_EXPR
, copy_to_permanent (type
), expr
);
705 return convert_from_reference (build_dynamic_cast_1 (type
, expr
));
708 /* Build and initialize various sorts of descriptors. Every descriptor
709 node has a name associated with it (the name created by mangling).
710 For this reason, we use the identifier as our access to the __*_desc
711 nodes, instead of sticking them directly in the types. Otherwise we
712 would burden all built-in types (and pointer types) with slots that
713 we don't necessarily want to use.
715 For each descriptor we build, we build a variable that contains
716 the descriptor's information. When we need this info at runtime,
717 all we need is access to these variables.
719 Note: these constructors always return the address of the descriptor
720 info, since that is simplest for their mutual interaction. */
722 extern tree const_string_type_node
;
724 /* Build an initializer for a __si_type_info node. */
727 expand_si_desc (tdecl
, type
)
732 const char *name
= build_overload_name (type
, 1, 1);
733 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
735 type
= BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0));
736 expand_expr_stmt (get_typeid_1 (type
));
737 t
= decay_conversion (get_tinfo_var (type
));
739 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
740 (NULL_TREE
, decay_conversion (name_string
), tree_cons
741 (NULL_TREE
, t
, NULL_TREE
)));
743 fn
= get_identifier ("__rtti_si");
744 if (IDENTIFIER_GLOBAL_VALUE (fn
))
745 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
749 push_obstacks (&permanent_obstack
, &permanent_obstack
);
751 (NULL_TREE
, ptr_type_node
, tree_cons
752 (NULL_TREE
, const_string_type_node
, tree_cons
753 (NULL_TREE
, build_pointer_type (type_info_type_node
),
755 tmp
= build_function_type (void_type_node
, tmp
);
757 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
758 DECL_EXTERNAL (fn
) = 1;
759 TREE_PUBLIC (fn
) = 1;
760 DECL_ARTIFICIAL (fn
) = 1;
761 pushdecl_top_level (fn
);
762 make_function_rtl (fn
);
767 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
768 expand_expr_stmt (fn
);
771 /* Build an initializer for a __class_type_info node. */
774 expand_class_desc (tdecl
, type
)
782 int i
= CLASSTYPE_N_BASECLASSES (type
);
784 tree binfos
= TYPE_BINFO_BASETYPES (type
);
786 /* See code below that used these. */
787 tree vb
= CLASSTYPE_VBASECLASSES (type
);
790 tree base
, elems
, access
, offset
, isvir
;
791 tree elt
, elts
= NULL_TREE
;
792 static tree base_info_type_node
;
794 if (base_info_type_node
== NULL_TREE
)
798 /* A reasonably close approximation of __class_type_info::base_info */
800 push_obstacks (&permanent_obstack
, &permanent_obstack
);
801 base_info_type_node
= make_lang_type (RECORD_TYPE
);
803 /* Actually const __user_type_info * */
804 fields
[0] = build_lang_field_decl
805 (FIELD_DECL
, NULL_TREE
,
806 build_pointer_type (build_qualified_type
807 (type_info_type_node
,
809 fields
[1] = build_lang_field_decl
810 (FIELD_DECL
, NULL_TREE
, unsigned_intSI_type_node
);
811 DECL_BIT_FIELD (fields
[1]) = 1;
812 DECL_FIELD_SIZE (fields
[1]) = 29;
814 fields
[2] = build_lang_field_decl
815 (FIELD_DECL
, NULL_TREE
, boolean_type_node
);
816 DECL_BIT_FIELD (fields
[2]) = 1;
817 DECL_FIELD_SIZE (fields
[2]) = 1;
819 /* Actually enum access */
820 fields
[3] = build_lang_field_decl
821 (FIELD_DECL
, NULL_TREE
, integer_type_node
);
822 DECL_BIT_FIELD (fields
[3]) = 1;
823 DECL_FIELD_SIZE (fields
[3]) = 2;
825 finish_builtin_type (base_info_type_node
, "__base_info", fields
,
832 tree binfo
= TREE_VEC_ELT (binfos
, i
);
834 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo
)));
835 base
= decay_conversion (get_tinfo_var (BINFO_TYPE (binfo
)));
837 if (TREE_VIA_VIRTUAL (binfo
))
839 tree t
= BINFO_TYPE (binfo
);
843 FORMAT_VBASE_NAME (name
, t
);
844 field
= lookup_field (type
, get_identifier (name
), 0, 0);
845 offset
= size_binop (FLOOR_DIV_EXPR
,
846 DECL_FIELD_BITPOS (field
), size_int (BITS_PER_UNIT
));
847 offset
= convert (sizetype
, offset
);
850 offset
= BINFO_OFFSET (binfo
);
852 if (TREE_VIA_PUBLIC (binfo
))
853 access
= access_public_node
;
854 else if (TREE_VIA_PROTECTED (binfo
))
855 access
= access_protected_node
;
857 access
= access_private_node
;
858 if (TREE_VIA_VIRTUAL (binfo
))
859 isvir
= boolean_true_node
;
861 isvir
= boolean_false_node
;
864 (CONSTRUCTOR
, base_info_type_node
, NULL_TREE
, tree_cons
865 (NULL_TREE
, base
, tree_cons
866 (NULL_TREE
, offset
, tree_cons
867 (NULL_TREE
, isvir
, tree_cons
868 (NULL_TREE
, access
, NULL_TREE
)))));
869 TREE_HAS_CONSTRUCTOR (elt
) = TREE_CONSTANT (elt
) = TREE_STATIC (elt
) = 1;
870 elts
= expr_tree_cons (NULL_TREE
, elt
, elts
);
878 access
= access_public_node
;
881 b
= TREE_VEC_ELT (binfos
, i
);
882 if (BINFO_TYPE (vb
) == BINFO_TYPE (b
) && TREE_VIA_VIRTUAL (b
))
884 if (TREE_VIA_PUBLIC (b
))
885 access
= access_public_node
;
886 else if (TREE_VIA_PROTECTED (b
))
887 access
= access_protected_node
;
889 access
= access_private_node
;
893 base
= build_t_desc (BINFO_TYPE (vb
), 1);
894 offset
= BINFO_OFFSET (vb
);
895 isvir
= build_int_2 (1, 0);
897 base_list
= expr_tree_cons (NULL_TREE
, base
, base_list
);
898 isvir_list
= expr_tree_cons (NULL_TREE
, isvir
, isvir_list
);
899 acc_list
= expr_tree_cons (NULL_TREE
, access
, acc_list
);
900 off_list
= expr_tree_cons (NULL_TREE
, offset
, off_list
);
903 vb
= TREE_CHAIN (vb
);
907 name
= build_overload_name (type
, 1, 1);
908 name_string
= combine_strings (build_string (strlen (name
)+1, name
));
911 tree arrtype
= build_array_type (base_info_type_node
, NULL_TREE
);
912 elts
= build (CONSTRUCTOR
, arrtype
, NULL_TREE
, elts
);
913 TREE_HAS_CONSTRUCTOR (elts
) = TREE_CONSTANT (elts
)
914 = TREE_STATIC (elts
) = 1;
915 complete_array_type (arrtype
, elts
, 1);
919 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
920 (NULL_TREE
, decay_conversion (name_string
), tree_cons
921 (NULL_TREE
, decay_conversion (elts
), tree_cons
922 (NULL_TREE
, cp_convert (sizetype
, build_int_2 (base_cnt
, 0)),
925 fn
= get_identifier ("__rtti_class");
926 if (IDENTIFIER_GLOBAL_VALUE (fn
))
927 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
930 push_obstacks (&permanent_obstack
, &permanent_obstack
);
932 (NULL_TREE
, ptr_type_node
, tree_cons
933 (NULL_TREE
, const_string_type_node
, tree_cons
934 (NULL_TREE
, build_pointer_type (base_info_type_node
), tree_cons
935 (NULL_TREE
, sizetype
, void_list_node
))));
936 tmp
= build_function_type (void_type_node
, tmp
);
938 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
939 DECL_EXTERNAL (fn
) = 1;
940 TREE_PUBLIC (fn
) = 1;
941 DECL_ARTIFICIAL (fn
) = 1;
942 pushdecl_top_level (fn
);
943 make_function_rtl (fn
);
948 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
949 expand_expr_stmt (fn
);
952 /* Build an initializer for a __pointer_type_info node. */
955 expand_ptr_desc (tdecl
, type
)
960 const char *name
= build_overload_name (type
, 1, 1);
961 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
963 type
= TREE_TYPE (type
);
964 expand_expr_stmt (get_typeid_1 (type
));
965 t
= decay_conversion (get_tinfo_var (type
));
967 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
968 (NULL_TREE
, decay_conversion (name_string
), tree_cons
969 (NULL_TREE
, t
, NULL_TREE
)));
971 fn
= get_identifier ("__rtti_ptr");
972 if (IDENTIFIER_GLOBAL_VALUE (fn
))
973 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
977 push_obstacks (&permanent_obstack
, &permanent_obstack
);
979 (NULL_TREE
, ptr_type_node
, tree_cons
980 (NULL_TREE
, const_string_type_node
, tree_cons
981 (NULL_TREE
, build_pointer_type (type_info_type_node
),
983 tmp
= build_function_type (void_type_node
, tmp
);
985 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
986 DECL_EXTERNAL (fn
) = 1;
987 TREE_PUBLIC (fn
) = 1;
988 DECL_ARTIFICIAL (fn
) = 1;
989 pushdecl_top_level (fn
);
990 make_function_rtl (fn
);
995 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
996 expand_expr_stmt (fn
);
999 /* Build an initializer for a __attr_type_info node. */
1002 expand_attr_desc (tdecl
, type
)
1007 const char *name
= build_overload_name (type
, 1, 1);
1008 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1009 tree attrval
= build_int_2 (TYPE_QUALS (type
), 0);
1011 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type
)));
1012 t
= decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type
)));
1014 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1015 (NULL_TREE
, decay_conversion (name_string
), tree_cons
1016 (NULL_TREE
, attrval
, expr_tree_cons (NULL_TREE
, t
, NULL_TREE
))));
1018 fn
= get_identifier ("__rtti_attr");
1019 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1020 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1024 push_obstacks (&permanent_obstack
, &permanent_obstack
);
1026 (NULL_TREE
, ptr_type_node
, tree_cons
1027 (NULL_TREE
, const_string_type_node
, tree_cons
1028 (NULL_TREE
, integer_type_node
, tree_cons
1029 (NULL_TREE
, build_pointer_type (type_info_type_node
),
1031 tmp
= build_function_type (void_type_node
, tmp
);
1033 fn
= build_lang_decl (FUNCTION_DECL
, fn
, tmp
);
1034 DECL_EXTERNAL (fn
) = 1;
1035 TREE_PUBLIC (fn
) = 1;
1036 DECL_ARTIFICIAL (fn
) = 1;
1037 pushdecl_top_level (fn
);
1038 make_function_rtl (fn
);
1043 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1044 expand_expr_stmt (fn
);
1047 /* Build an initializer for a type_info node that just has a name. */
1050 expand_generic_desc (tdecl
, type
, fnname
)
1055 const char *name
= build_overload_name (type
, 1, 1);
1056 tree name_string
= combine_strings (build_string (strlen (name
)+1, name
));
1057 tree elems
= tree_cons
1058 (NULL_TREE
, decay_conversion (tdecl
), tree_cons
1059 (NULL_TREE
, decay_conversion (name_string
), NULL_TREE
));
1061 tree fn
= get_identifier (fnname
);
1062 if (IDENTIFIER_GLOBAL_VALUE (fn
))
1063 fn
= IDENTIFIER_GLOBAL_VALUE (fn
);
1067 push_obstacks (&permanent_obstack
, &permanent_obstack
);
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
);
1083 fn
= build_call (fn
, TREE_TYPE (TREE_TYPE (fn
)), elems
);
1084 expand_expr_stmt (fn
);
1087 /* Generate the code for a type_info initialization function.
1088 Note that we take advantage of the passage
1090 5.2.7 Type identification [expr.typeid]
1092 Whether or not the destructor is called for the type_info object at the
1093 end of the program is unspecified.
1095 and don't bother to arrange for these objects to be destroyed. It
1096 doesn't matter, anyway, since the destructors don't do anything.
1098 This must only be called from toplevel (i.e. from finish_file)! */
1101 synthesize_tinfo_fn (fndecl
)
1104 tree type
= TREE_TYPE (DECL_NAME (fndecl
));
1105 tree tmp
, addr
, tdecl
;
1109 import_export_decl (fndecl
);
1110 if (DECL_REALLY_EXTERN (fndecl
))
1114 tdecl
= get_tinfo_var (type
);
1115 DECL_EXTERNAL (tdecl
) = 0;
1116 TREE_STATIC (tdecl
) = 1;
1117 DECL_COMMON (tdecl
) = 1;
1118 TREE_USED (tdecl
) = 1;
1119 DECL_ALIGN (tdecl
) = TYPE_ALIGN (ptr_type_node
);
1120 cp_finish_decl (tdecl
, NULL_TREE
, NULL_TREE
, 0, 0);
1122 start_function (NULL_TREE
, fndecl
, NULL_TREE
, 1);
1123 store_parm_decls ();
1127 /* If the first word of the array (the vtable) is non-zero, we've already
1128 initialized the object, so don't do it again. */
1129 addr
= decay_conversion (tdecl
);
1130 tmp
= cp_convert (build_pointer_type (ptr_type_node
), addr
);
1131 tmp
= build_indirect_ref (tmp
, 0);
1132 tmp
= build_binary_op (EQ_EXPR
, tmp
, integer_zero_node
, 1);
1133 expand_start_cond (tmp
, 0);
1135 if (TREE_CODE (type
) == FUNCTION_TYPE
)
1136 expand_generic_desc (tdecl
, type
, "__rtti_func");
1137 else if (TREE_CODE (type
) == ARRAY_TYPE
)
1138 expand_generic_desc (tdecl
, type
, "__rtti_array");
1139 else if (TYPE_QUALS (type
) != TYPE_UNQUALIFIED
)
1140 expand_attr_desc (tdecl
, type
);
1141 else if (TREE_CODE (type
) == POINTER_TYPE
)
1143 if (TREE_CODE (TREE_TYPE (type
)) == OFFSET_TYPE
)
1144 expand_generic_desc (tdecl
, type
, "__rtti_ptmd");
1145 else if (TREE_CODE (TREE_TYPE (type
)) == METHOD_TYPE
)
1146 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1148 expand_ptr_desc (tdecl
, type
);
1150 else if (TYPE_PTRMEMFUNC_P (type
))
1151 expand_generic_desc (tdecl
, type
, "__rtti_ptmf");
1152 else if (IS_AGGR_TYPE (type
))
1154 if (CLASSTYPE_N_BASECLASSES (type
) == 0)
1155 expand_generic_desc (tdecl
, type
, "__rtti_user");
1156 else if (! TYPE_USES_COMPLEX_INHERITANCE (type
)
1158 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type
), 0))))
1159 expand_si_desc (tdecl
, type
);
1161 expand_class_desc (tdecl
, type
);
1163 else if (TREE_CODE (type
) == ENUMERAL_TYPE
)
1164 expand_generic_desc (tdecl
, type
, "__rtti_user");
1166 my_friendly_abort (252);
1170 /* OK, now return the type_info object. */
1171 tmp
= cp_convert (build_pointer_type (type_info_type_node
), addr
);
1172 tmp
= build_indirect_ref (tmp
, 0);
1173 c_expand_return (tmp
);
1174 finish_function (lineno
, 0, 0);