* cp-tree.def (SCOPE_STMT): Take one operand.
[official-gcc.git] / gcc / cp / rtti.c
blob3f8300ff6e33e3965f60426b93bebe622856d209
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)
10 any later version.
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. */
23 #include "config.h"
24 #include "system.h"
25 #include "tree.h"
26 #include "cp-tree.h"
27 #include "flags.h"
28 #include "output.h"
29 #include "assert.h"
30 #include "toplev.h"
32 #ifndef INT_TYPE_SIZE
33 #define INT_TYPE_SIZE BITS_PER_WORD
34 #endif
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 void
53 init_rtti_processing ()
55 if (flag_honor_std)
56 push_namespace (get_identifier ("std"));
57 type_info_type_node = xref_tag
58 (class_type_node, get_identifier ("type_info"), 1);
59 if (flag_honor_std)
60 pop_namespace ();
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,
64 TYPE_QUAL_CONST)),
65 void_list_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
71 that sub-object. */
73 static tree
74 build_headof_sub (exp)
75 tree 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);
82 return 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
88 expression. */
90 static tree
91 build_headof (exp)
92 tree exp;
94 tree type = TREE_TYPE (exp);
95 tree aref;
96 tree offset;
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))
106 return exp;
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)
123 offset = aref;
124 else
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. */
135 static tree
136 call_void_fn (name)
137 const char *name;
139 tree d = get_identifier (name);
140 tree type;
142 if (IDENTIFIER_GLOBAL_VALUE (d))
143 d = IDENTIFIER_GLOBAL_VALUE (d);
144 else
146 type = build_function_type (void_type_node, void_list_node);
147 d = build_lang_decl (FUNCTION_DECL, d, type);
148 DECL_EXTERNAL (d) = 1;
149 TREE_PUBLIC (d) = 1;
150 DECL_ARTIFICIAL (d) = 1;
151 pushdecl_top_level (d);
152 make_function_rtl (d);
155 mark_used (d);
156 return build_call (d, void_type_node, NULL_TREE);
159 /* Get a bad_cast node for the program to throw...
161 See libstdc++/exception.cc for __throw_bad_cast */
163 static tree
164 throw_bad_cast ()
166 return call_void_fn ("__throw_bad_cast");
169 static tree
170 throw_bad_typeid ()
172 return call_void_fn ("__throw_bad_typeid");
175 /* Return the type_info function associated with the expression EXP. If
176 EXP is a reference to a polymorphic class, return the dynamic type;
177 otherwise return the static type of the expression. */
179 tree
180 get_tinfo_fn_dynamic (exp)
181 tree exp;
183 tree type;
185 if (exp == error_mark_node)
186 return error_mark_node;
188 if (type_unknown_p (exp))
190 error ("typeid of overloaded function");
191 return error_mark_node;
194 type = TREE_TYPE (exp);
196 /* peel back references, so they match. */
197 if (TREE_CODE (type) == REFERENCE_TYPE)
198 type = TREE_TYPE (type);
200 /* Peel off cv qualifiers. */
201 type = TYPE_MAIN_VARIANT (type);
203 if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
205 cp_error ("taking typeid of incomplete type `%T'", type);
206 return error_mark_node;
209 /* If exp is a reference to polymorphic type, get the real type_info. */
210 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
212 /* build reference to type_info from vtable. */
213 tree t;
215 if (! flag_rtti)
216 error ("taking dynamic typeid of object with -fno-rtti");
217 if (CLASSTYPE_COM_INTERFACE (type))
219 cp_error ("RTTI not supported for COM interface type `%T'", type);
220 return error_mark_node;
223 /* If we don't have rtti stuff, get to a sub-object that does. */
224 if (! CLASSTYPE_VFIELDS (type))
226 exp = build_unary_op (ADDR_EXPR, exp, 0);
227 exp = build_headof_sub (exp);
228 exp = build_indirect_ref (exp, NULL_PTR);
231 if (flag_vtable_thunks)
232 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
233 else
234 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
235 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
236 return t;
239 /* otherwise return the type_info for the static type of the expr. */
240 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
243 tree
244 build_typeid (exp)
245 tree exp;
247 exp = get_tinfo_fn_dynamic (exp);
248 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
249 return convert_from_reference (exp);
252 tree
253 build_x_typeid (exp)
254 tree exp;
256 tree cond = NULL_TREE;
257 tree type;
258 int nonnull;
260 if (! flag_rtti)
262 error ("cannot use typeid with -fno-rtti");
263 return error_mark_node;
266 if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
268 error ("must #include <typeinfo> before using typeid");
269 return error_mark_node;
272 if (processing_template_decl)
273 return build_min_nt (TYPEID_EXPR, exp);
275 if (TREE_CODE (exp) == INDIRECT_REF
276 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
277 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
278 && ! resolves_to_fixed_type_p (exp, &nonnull)
279 && ! nonnull)
281 exp = stabilize_reference (exp);
282 cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
285 exp = get_tinfo_fn_dynamic (exp);
287 if (exp == error_mark_node)
288 return error_mark_node;
290 type = TREE_TYPE (tinfo_fn_type);
291 exp = build_call (exp, type, NULL_TREE);
293 if (cond)
295 tree bad = throw_bad_typeid ();
297 bad = build_compound_expr
298 (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);
306 static tree
307 get_tinfo_var (type)
308 tree type;
310 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
311 tree tdecl, arrtype;
312 int size;
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)
331 && (TREE_VIA_PUBLIC
332 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
333 size = 3 * POINTER_SIZE;
334 else
335 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
337 else
338 size = 2 * POINTER_SIZE;
340 /* The type for a character array of the appropriate size. */
341 arrtype = build_cplus_array_type
342 (unsigned_char_type_node,
343 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
345 tdecl = build_decl (VAR_DECL, tname, arrtype);
346 TREE_PUBLIC (tdecl) = 1;
347 DECL_EXTERNAL (tdecl) = 1;
348 DECL_ARTIFICIAL (tdecl) = 1;
349 push_to_top_level ();
350 pushdecl (tdecl);
351 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0);
352 pop_from_top_level ();
354 return tdecl;
357 /* Returns the decl for a function which will return a type_info node for
358 TYPE. This version does not mark the function used, for use in
359 set_rtti_entry; for the vtable case, we'll get marked in
360 finish_vtable_vardecl, when we know that we want to be emitted.
362 We do this to avoid emitting the tinfo node itself, since we don't
363 currently support DECL_DEFER_OUTPUT for variables. Also, we don't
364 associate constant pools with their functions properly, so we would
365 emit string constants and such even though we don't emit the actual
366 function. When those bugs are fixed, this function should go away. */
368 tree
369 get_tinfo_fn_unused (type)
370 tree type;
372 tree name;
373 tree d;
375 if (TREE_CODE (type) == OFFSET_TYPE)
376 type = TREE_TYPE (type);
377 if (TREE_CODE (type) == METHOD_TYPE)
378 type = build_function_type (TREE_TYPE (type),
379 TREE_CHAIN (TYPE_ARG_TYPES (type)));
381 name = build_overload_with_type (tinfo_fn_id, type);
383 if (IDENTIFIER_GLOBAL_VALUE (name))
384 return IDENTIFIER_GLOBAL_VALUE (name);
386 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
387 DECL_EXTERNAL (d) = 1;
388 TREE_PUBLIC (d) = 1;
389 DECL_ARTIFICIAL (d) = 1;
390 DECL_NOT_REALLY_EXTERN (d) = 1;
391 SET_DECL_TINFO_FN_P (d);
392 TREE_TYPE (name) = type;
394 pushdecl_top_level (d);
395 make_function_rtl (d);
396 mark_inline_for_output (d);
398 return d;
401 /* Likewise, but also mark it used. Called by various EH and RTTI code. */
403 tree
404 get_tinfo_fn (type)
405 tree type;
407 tree d = get_tinfo_fn_unused (type);
408 mark_used (d);
409 return d;
412 tree
413 get_typeid_1 (type)
414 tree type;
416 tree t;
418 t = build_call
419 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
420 return convert_from_reference (t);
423 /* Return the type_info object for TYPE, creating it if necessary. */
425 tree
426 get_typeid (type)
427 tree type;
429 if (type == error_mark_node)
430 return error_mark_node;
432 if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
434 error ("must #include <typeinfo> before using typeid");
435 return error_mark_node;
438 if (processing_template_decl)
439 return build_min_nt (TYPEID_EXPR, type);
441 /* If the type of the type-id is a reference type, the result of the
442 typeid expression refers to a type_info object representing the
443 referenced type. */
444 if (TREE_CODE (type) == REFERENCE_TYPE)
445 type = TREE_TYPE (type);
447 /* The top-level cv-qualifiers of the lvalue expression or the type-id
448 that is the operand of typeid are always ignored. */
449 type = TYPE_MAIN_VARIANT (type);
451 if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
453 cp_error ("taking typeid of incomplete type `%T'", type);
454 return error_mark_node;
457 return get_typeid_1 (type);
460 /* Check whether TEST is null before returning RESULT. If TEST is used in
461 RESULT, it must have previously had a save_expr applied to it. */
463 static tree
464 ifnonnull (test, result)
465 tree test, result;
467 return build (COND_EXPR, TREE_TYPE (result),
468 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
469 cp_convert (TREE_TYPE (result), integer_zero_node),
470 result);
473 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
474 paper. */
476 static tree
477 build_dynamic_cast_1 (type, expr)
478 tree type, expr;
480 enum tree_code tc = TREE_CODE (type);
481 tree exprtype;
482 enum tree_code ec;
483 tree dcast_fn;
484 tree old_expr = expr;
486 if (TREE_CODE (expr) == OFFSET_REF)
487 expr = resolve_offset_ref (expr);
489 exprtype = TREE_TYPE (expr);
490 assert (exprtype != NULL_TREE);
491 ec = TREE_CODE (exprtype);
493 switch (tc)
495 case POINTER_TYPE:
496 if (ec == REFERENCE_TYPE)
498 expr = convert_from_reference (expr);
499 exprtype = TREE_TYPE (expr);
500 ec = TREE_CODE (exprtype);
502 if (ec != POINTER_TYPE)
503 goto fail;
504 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
505 goto fail;
506 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
507 goto fail;
508 if (!at_least_as_qualified_p (TREE_TYPE (type),
509 TREE_TYPE (exprtype)))
510 goto fail;
511 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
512 break;
513 /* else fall through */
514 case REFERENCE_TYPE:
515 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
516 goto fail;
517 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
518 goto fail;
519 break;
520 /* else fall through */
521 default:
522 goto fail;
525 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
526 if (ec == RECORD_TYPE)
528 exprtype = build_reference_type (exprtype);
529 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
530 LOOKUP_NORMAL, NULL_TREE);
531 ec = REFERENCE_TYPE;
534 if (tc == REFERENCE_TYPE)
536 if (ec != REFERENCE_TYPE)
537 goto fail;
538 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
539 goto fail;
540 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
541 goto fail;
542 if (!at_least_as_qualified_p (TREE_TYPE (type),
543 TREE_TYPE (exprtype)))
544 goto fail;
547 /* If *type is an unambiguous accessible base class of *exprtype,
548 convert statically. */
550 int distance;
551 tree path;
553 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
554 &path);
556 if (distance == -2)
558 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
559 TREE_TYPE (exprtype), TREE_TYPE (type));
560 return error_mark_node;
562 if (distance == -3)
564 cp_error ("dynamic_cast from `%T' to private base class `%T'",
565 TREE_TYPE (exprtype), TREE_TYPE (type));
566 return error_mark_node;
569 if (distance >= 0)
570 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
573 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
574 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
576 tree expr1;
577 /* if TYPE is `void *', return pointer to complete object. */
578 if (tc == POINTER_TYPE
579 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
581 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
582 if (TREE_CODE (expr) == ADDR_EXPR
583 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
584 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
585 return build1 (NOP_EXPR, type, expr);
587 /* Since expr is used twice below, save it. */
588 expr = save_expr (expr);
590 expr1 = build_headof (expr);
591 if (TREE_TYPE (expr1) != type)
592 expr1 = build1 (NOP_EXPR, type, expr1);
593 return ifnonnull (expr, expr1);
595 else
597 tree retval;
598 tree result, td1, td2, td3, elems, expr2;
599 tree static_type, target_type, boff;
601 /* If we got here, we can't convert statically. Therefore,
602 dynamic_cast<D&>(b) (b an object) cannot succeed. */
603 if (ec == REFERENCE_TYPE)
605 if (TREE_CODE (old_expr) == VAR_DECL
606 && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
608 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
609 old_expr, type);
610 return throw_bad_cast ();
613 /* Ditto for dynamic_cast<D*>(&b). */
614 else if (TREE_CODE (expr) == ADDR_EXPR)
616 tree op = TREE_OPERAND (expr, 0);
617 if (TREE_CODE (op) == VAR_DECL
618 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
620 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
621 op, type);
622 retval = build_int_2 (0, 0);
623 TREE_TYPE (retval) = type;
624 return retval;
628 /* Since expr is used twice below, save it. */
629 expr = save_expr (expr);
631 expr1 = expr;
632 if (tc == REFERENCE_TYPE)
633 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
635 /* Build run-time conversion. */
636 expr2 = build_headof (expr1);
638 if (ec == POINTER_TYPE)
639 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
640 else
641 td1 = get_tinfo_fn_dynamic (expr);
642 td1 = decay_conversion (td1);
644 target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
645 static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
646 td2 = decay_conversion (get_tinfo_fn (target_type));
647 td3 = decay_conversion (get_tinfo_fn (static_type));
649 /* Determine how T and V are related. */
650 boff = get_dynamic_cast_base_type (static_type, target_type);
652 elems = tree_cons
653 (NULL_TREE, td1, tree_cons
654 (NULL_TREE, td2, tree_cons
655 (NULL_TREE, boff, tree_cons
656 (NULL_TREE, expr2, tree_cons
657 (NULL_TREE, td3, tree_cons
658 (NULL_TREE, expr1, NULL_TREE))))));
660 dcast_fn = get_identifier ("__dynamic_cast_2");
661 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
662 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
663 else
665 tree tmp;
667 tmp = tree_cons
668 (NULL_TREE, TREE_TYPE (td1), tree_cons
669 (NULL_TREE, TREE_TYPE (td1), tree_cons
670 (NULL_TREE, integer_type_node, tree_cons
671 (NULL_TREE, ptr_type_node, tree_cons
672 (NULL_TREE, TREE_TYPE (td1), tree_cons
673 (NULL_TREE, ptr_type_node, void_list_node))))));
674 tmp = build_function_type (ptr_type_node, tmp);
675 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
676 DECL_EXTERNAL (dcast_fn) = 1;
677 TREE_PUBLIC (dcast_fn) = 1;
678 DECL_ARTIFICIAL (dcast_fn) = 1;
679 pushdecl_top_level (dcast_fn);
680 make_function_rtl (dcast_fn);
683 mark_used (dcast_fn);
684 result = build_call
685 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
687 if (tc == REFERENCE_TYPE)
689 expr1 = throw_bad_cast ();
690 expr1 = build_compound_expr
691 (tree_cons (NULL_TREE, expr1,
692 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
693 TREE_TYPE (expr1) = type;
694 result = save_expr (result);
695 return build (COND_EXPR, type, result, result, expr1);
698 /* Now back to the type we want from a void*. */
699 result = cp_convert (type, result);
700 return ifnonnull (expr, result);
704 cp_error ("dynamic_cast from non-polymorphic type `%#T'", exprtype);
705 return error_mark_node;
707 fail:
708 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
709 expr, exprtype, type);
710 return error_mark_node;
713 tree
714 build_dynamic_cast (type, expr)
715 tree type, expr;
717 if (type == error_mark_node || expr == error_mark_node)
718 return error_mark_node;
720 if (processing_template_decl)
721 return build_min (DYNAMIC_CAST_EXPR, type, expr);
723 return convert_from_reference (build_dynamic_cast_1 (type, expr));
726 /* Build and initialize various sorts of descriptors. Every descriptor
727 node has a name associated with it (the name created by mangling).
728 For this reason, we use the identifier as our access to the __*_desc
729 nodes, instead of sticking them directly in the types. Otherwise we
730 would burden all built-in types (and pointer types) with slots that
731 we don't necessarily want to use.
733 For each descriptor we build, we build a variable that contains
734 the descriptor's information. When we need this info at runtime,
735 all we need is access to these variables.
737 Note: these constructors always return the address of the descriptor
738 info, since that is simplest for their mutual interaction. */
740 /* Build an initializer for a __si_type_info node. */
742 static void
743 expand_si_desc (tdecl, type)
744 tree tdecl;
745 tree type;
747 tree t, elems, fn;
748 const char *name = build_overload_name (type, 1, 1);
749 tree name_string = combine_strings (build_string (strlen (name)+1, name));
751 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
752 finish_expr_stmt (get_typeid_1 (type));
753 t = decay_conversion (get_tinfo_var (type));
754 elems = tree_cons
755 (NULL_TREE, decay_conversion (tdecl), tree_cons
756 (NULL_TREE, decay_conversion (name_string), tree_cons
757 (NULL_TREE, t, NULL_TREE)));
759 fn = get_identifier ("__rtti_si");
760 if (IDENTIFIER_GLOBAL_VALUE (fn))
761 fn = IDENTIFIER_GLOBAL_VALUE (fn);
762 else
764 tree tmp;
765 tmp = tree_cons
766 (NULL_TREE, ptr_type_node, tree_cons
767 (NULL_TREE, const_string_type_node, tree_cons
768 (NULL_TREE, build_pointer_type (type_info_type_node),
769 void_list_node)));
770 tmp = build_function_type (void_type_node, tmp);
772 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
773 DECL_EXTERNAL (fn) = 1;
774 TREE_PUBLIC (fn) = 1;
775 DECL_ARTIFICIAL (fn) = 1;
776 pushdecl_top_level (fn);
777 make_function_rtl (fn);
780 mark_used (fn);
781 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
782 finish_expr_stmt (fn);
785 /* Build an initializer for a __class_type_info node. */
787 static void
788 expand_class_desc (tdecl, type)
789 tree tdecl;
790 tree type;
792 tree name_string;
793 tree fn, tmp;
794 const char *name;
796 int i = CLASSTYPE_N_BASECLASSES (type);
797 int base_cnt = 0;
798 tree binfos = TYPE_BINFO_BASETYPES (type);
799 #if 0
800 /* See code below that used these. */
801 tree vb = CLASSTYPE_VBASECLASSES (type);
802 int n_base = i;
803 #endif
804 tree base, elems, access, offset, isvir;
805 tree elt, elts = NULL_TREE;
806 static tree base_info_type_node;
808 if (base_info_type_node == NULL_TREE)
810 tree fields [4];
812 /* A reasonably close approximation of __class_type_info::base_info */
814 base_info_type_node = make_lang_type (RECORD_TYPE);
816 /* Actually const __user_type_info * */
817 fields [0] = build_lang_decl
818 (FIELD_DECL, NULL_TREE,
819 build_pointer_type (build_qualified_type
820 (type_info_type_node,
821 TYPE_QUAL_CONST)));
822 fields [1] = build_lang_decl
823 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
824 DECL_BIT_FIELD (fields[1]) = 1;
825 DECL_FIELD_SIZE (fields[1]) = 29;
827 fields [2] = build_lang_decl
828 (FIELD_DECL, NULL_TREE, boolean_type_node);
829 DECL_BIT_FIELD (fields[2]) = 1;
830 DECL_FIELD_SIZE (fields[2]) = 1;
832 /* Actually enum access */
833 fields [3] = build_lang_decl
834 (FIELD_DECL, NULL_TREE, integer_type_node);
835 DECL_BIT_FIELD (fields[3]) = 1;
836 DECL_FIELD_SIZE (fields[3]) = 2;
838 finish_builtin_type (base_info_type_node, "__base_info", fields,
839 3, ptr_type_node);
842 while (--i >= 0)
844 tree binfo = TREE_VEC_ELT (binfos, i);
846 finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
847 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
849 if (TREE_VIA_VIRTUAL (binfo))
851 tree t = BINFO_TYPE (binfo);
852 const char *name;
853 tree field;
855 FORMAT_VBASE_NAME (name, t);
856 field = lookup_field (type, get_identifier (name), 0, 0);
857 offset = size_binop (FLOOR_DIV_EXPR,
858 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
859 offset = convert (sizetype, offset);
861 else
862 offset = BINFO_OFFSET (binfo);
864 if (TREE_VIA_PUBLIC (binfo))
865 access = access_public_node;
866 else if (TREE_VIA_PROTECTED (binfo))
867 access = access_protected_node;
868 else
869 access = access_private_node;
870 if (TREE_VIA_VIRTUAL (binfo))
871 isvir = boolean_true_node;
872 else
873 isvir = boolean_false_node;
875 elt = build
876 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
877 (NULL_TREE, base, tree_cons
878 (NULL_TREE, offset, tree_cons
879 (NULL_TREE, isvir, tree_cons
880 (NULL_TREE, access, NULL_TREE)))));
881 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
882 elts = tree_cons (NULL_TREE, elt, elts);
883 base_cnt++;
885 #if 0
886 i = n_base;
887 while (vb)
889 tree b;
890 access = access_public_node;
891 while (--i >= 0)
893 b = TREE_VEC_ELT (binfos, i);
894 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
896 if (TREE_VIA_PUBLIC (b))
897 access = access_public_node;
898 else if (TREE_VIA_PROTECTED (b))
899 access = access_protected_node;
900 else
901 access = access_private_node;
902 break;
905 base = build_t_desc (BINFO_TYPE (vb), 1);
906 offset = BINFO_OFFSET (vb);
907 isvir = build_int_2 (1, 0);
909 base_list = tree_cons (NULL_TREE, base, base_list);
910 isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
911 acc_list = tree_cons (NULL_TREE, access, acc_list);
912 off_list = tree_cons (NULL_TREE, offset, off_list);
914 base_cnt++;
915 vb = TREE_CHAIN (vb);
917 #endif
919 name = build_overload_name (type, 1, 1);
920 name_string = combine_strings (build_string (strlen (name)+1, name));
923 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
924 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
925 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
926 = TREE_STATIC (elts) = 1;
927 complete_array_type (arrtype, elts, 1);
930 elems = tree_cons
931 (NULL_TREE, decay_conversion (tdecl), tree_cons
932 (NULL_TREE, decay_conversion (name_string), tree_cons
933 (NULL_TREE, decay_conversion (elts), tree_cons
934 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
935 NULL_TREE))));
937 fn = get_identifier ("__rtti_class");
938 if (IDENTIFIER_GLOBAL_VALUE (fn))
939 fn = IDENTIFIER_GLOBAL_VALUE (fn);
940 else
942 tmp = tree_cons
943 (NULL_TREE, ptr_type_node, tree_cons
944 (NULL_TREE, const_string_type_node, tree_cons
945 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
946 (NULL_TREE, sizetype, void_list_node))));
947 tmp = build_function_type (void_type_node, tmp);
949 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
950 DECL_EXTERNAL (fn) = 1;
951 TREE_PUBLIC (fn) = 1;
952 DECL_ARTIFICIAL (fn) = 1;
953 pushdecl_top_level (fn);
954 make_function_rtl (fn);
957 mark_used (fn);
958 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
959 finish_expr_stmt (fn);
962 /* Build an initializer for a __pointer_type_info node. */
964 static void
965 expand_ptr_desc (tdecl, type)
966 tree tdecl;
967 tree type;
969 tree t, elems, fn;
970 const char *name = build_overload_name (type, 1, 1);
971 tree name_string = combine_strings (build_string (strlen (name)+1, name));
973 type = TREE_TYPE (type);
974 finish_expr_stmt (get_typeid_1 (type));
975 t = decay_conversion (get_tinfo_var (type));
976 elems = tree_cons
977 (NULL_TREE, decay_conversion (tdecl), tree_cons
978 (NULL_TREE, decay_conversion (name_string), tree_cons
979 (NULL_TREE, t, NULL_TREE)));
981 fn = get_identifier ("__rtti_ptr");
982 if (IDENTIFIER_GLOBAL_VALUE (fn))
983 fn = IDENTIFIER_GLOBAL_VALUE (fn);
984 else
986 tree tmp;
987 tmp = tree_cons
988 (NULL_TREE, ptr_type_node, tree_cons
989 (NULL_TREE, const_string_type_node, tree_cons
990 (NULL_TREE, build_pointer_type (type_info_type_node),
991 void_list_node)));
992 tmp = build_function_type (void_type_node, tmp);
994 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
995 DECL_EXTERNAL (fn) = 1;
996 TREE_PUBLIC (fn) = 1;
997 DECL_ARTIFICIAL (fn) = 1;
998 pushdecl_top_level (fn);
999 make_function_rtl (fn);
1002 mark_used (fn);
1003 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1004 finish_expr_stmt (fn);
1007 /* Build an initializer for a __attr_type_info node. */
1009 static void
1010 expand_attr_desc (tdecl, type)
1011 tree tdecl;
1012 tree type;
1014 tree elems, t, fn;
1015 const char *name = build_overload_name (type, 1, 1);
1016 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1017 tree attrval = build_int_2 (TYPE_QUALS (type), 0);
1019 finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
1020 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
1021 elems = tree_cons
1022 (NULL_TREE, decay_conversion (tdecl), tree_cons
1023 (NULL_TREE, decay_conversion (name_string), tree_cons
1024 (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
1026 fn = get_identifier ("__rtti_attr");
1027 if (IDENTIFIER_GLOBAL_VALUE (fn))
1028 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1029 else
1031 tree tmp;
1032 tmp = tree_cons
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),
1037 void_list_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);
1048 mark_used (fn);
1049 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1050 finish_expr_stmt (fn);
1053 /* Build an initializer for a type_info node that just has a name. */
1055 static void
1056 expand_generic_desc (tdecl, type, fnname)
1057 tree tdecl;
1058 tree type;
1059 const char *fnname;
1061 const char *name = build_overload_name (type, 1, 1);
1062 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1063 tree elems = tree_cons
1064 (NULL_TREE, decay_conversion (tdecl), tree_cons
1065 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1067 tree fn = get_identifier (fnname);
1068 if (IDENTIFIER_GLOBAL_VALUE (fn))
1069 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1070 else
1072 tree tmp;
1073 tmp = tree_cons
1074 (NULL_TREE, ptr_type_node, tree_cons
1075 (NULL_TREE, const_string_type_node, void_list_node));
1076 tmp = build_function_type (void_type_node, tmp);
1078 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1079 DECL_EXTERNAL (fn) = 1;
1080 TREE_PUBLIC (fn) = 1;
1081 DECL_ARTIFICIAL (fn) = 1;
1082 pushdecl_top_level (fn);
1083 make_function_rtl (fn);
1086 mark_used (fn);
1087 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1088 finish_expr_stmt (fn);
1091 /* Generate the code for a type_info initialization function.
1092 Note that we take advantage of the passage
1094 5.2.7 Type identification [expr.typeid]
1096 Whether or not the destructor is called for the type_info object at the
1097 end of the program is unspecified.
1099 and don't bother to arrange for these objects to be destroyed. It
1100 doesn't matter, anyway, since the destructors don't do anything.
1102 This must only be called from toplevel (i.e. from finish_file)! */
1104 void
1105 synthesize_tinfo_fn (fndecl)
1106 tree fndecl;
1108 tree type = TREE_TYPE (DECL_NAME (fndecl));
1109 tree tmp, addr, tdecl;
1110 tree compound_stmt;
1111 tree if_stmt;
1112 tree then_clause;
1114 if (at_eof)
1116 import_export_decl (fndecl);
1117 if (DECL_REALLY_EXTERN (fndecl))
1118 return;
1121 /* Declare the static typeinfo variable. */
1122 tdecl = get_tinfo_var (type);
1123 DECL_EXTERNAL (tdecl) = 0;
1124 TREE_STATIC (tdecl) = 1;
1125 DECL_COMMON (tdecl) = 1;
1126 TREE_USED (tdecl) = 1;
1127 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1128 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0);
1130 /* Begin processing the function. */
1131 start_function (NULL_TREE, fndecl, NULL_TREE,
1132 SF_DEFAULT | SF_PRE_PARSED);
1133 DECL_DEFER_OUTPUT (fndecl) = 1;
1134 store_parm_decls ();
1135 clear_last_expr ();
1137 /* Begin the body of the function. */
1138 compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
1140 /* For convenience, we save away the address of the static
1141 variable. */
1142 addr = decay_conversion (tdecl);
1144 /* If the first word of the array (the vtable) is non-zero, we've already
1145 initialized the object, so don't do it again. */
1146 if_stmt = begin_if_stmt ();
1147 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1148 tmp = build_indirect_ref (tmp, 0);
1149 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node);
1150 finish_if_stmt_cond (tmp, if_stmt);
1151 then_clause = begin_compound_stmt (/*has_no_scope=*/0);
1153 if (TREE_CODE (type) == FUNCTION_TYPE)
1154 expand_generic_desc (tdecl, type, "__rtti_func");
1155 else if (TREE_CODE (type) == ARRAY_TYPE)
1156 expand_generic_desc (tdecl, type, "__rtti_array");
1157 else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
1158 expand_attr_desc (tdecl, type);
1159 else if (TREE_CODE (type) == POINTER_TYPE)
1161 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1162 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1163 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1164 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1165 else
1166 expand_ptr_desc (tdecl, type);
1168 else if (TYPE_PTRMEMFUNC_P (type))
1169 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1170 else if (IS_AGGR_TYPE (type))
1172 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1173 expand_generic_desc (tdecl, type, "__rtti_user");
1174 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1175 && (TREE_VIA_PUBLIC
1176 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1177 expand_si_desc (tdecl, type);
1178 else
1179 expand_class_desc (tdecl, type);
1181 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1182 expand_generic_desc (tdecl, type, "__rtti_user");
1183 else
1184 my_friendly_abort (252);
1186 finish_compound_stmt (/*has_no_scope=*/0, then_clause);
1187 finish_then_clause (if_stmt);
1188 finish_if_stmt ();
1190 /* OK, now return the type_info object. */
1191 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1192 tmp = build_indirect_ref (tmp, 0);
1193 finish_return_stmt (tmp);
1194 /* Finish the function body. */
1195 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
1196 expand_body (finish_function (lineno, 0));