1998-09-21 Ben Elliston <bje@cygnus.com>
[official-gcc.git] / gcc / cp / rtti.c
blob01c4a861ec25b0e1091c2369b0fdf013aea0382d
1 /* RunTime Type Identification
2 Copyright (C) 1995, 1996 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((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 get_typeid_1 PROTO((tree));
43 static tree ifnonnull PROTO((tree, tree));
44 static tree build_dynamic_cast_1 PROTO((tree, tree));
45 static void expand_si_desc PROTO((tree, tree));
46 static void expand_class_desc PROTO((tree, tree));
47 static void expand_attr_desc PROTO((tree, tree));
48 static void expand_ptr_desc PROTO((tree, tree));
49 static void expand_generic_desc PROTO((tree, tree, char *));
50 static tree throw_bad_cast PROTO((void));
51 static tree throw_bad_typeid PROTO((void));
53 tree type_info_type_node;
54 tree tinfo_fn_id;
55 tree tinfo_fn_type;
57 void
58 init_rtti_processing ()
60 if (flag_honor_std)
61 push_namespace (get_identifier ("std"));
62 type_info_type_node = xref_tag
63 (class_type_node, get_identifier ("type_info"), 1);
64 if (flag_honor_std)
65 pop_namespace ();
66 tinfo_fn_id = get_identifier ("__tf");
67 tinfo_fn_type = build_function_type
68 (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
69 void_list_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
75 that sub-object. */
77 static tree
78 build_headof_sub (exp)
79 tree 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);
86 return 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
92 expression. */
94 static tree
95 build_headof (exp)
96 tree exp;
98 tree type = TREE_TYPE (exp);
99 tree aref;
100 tree offset;
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))
110 return exp;
112 /* If we don't have rtti stuff, get to a sub-object that does. */
113 if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
114 exp = build_headof_sub (exp);
116 /* We use this a couple of times below, protect it. */
117 exp = save_expr (exp);
119 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
121 if (flag_vtable_thunks)
122 offset = aref;
123 else
124 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
126 type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
127 TREE_THIS_VOLATILE (exp));
128 return build (PLUS_EXPR, type, exp,
129 cp_convert (ptrdiff_type_node, offset));
132 /* Build a call to a generic entry point taking and returning void. */
134 static tree
135 call_void_fn (name)
136 char *name;
138 tree d = get_identifier (name);
139 tree type;
141 if (IDENTIFIER_GLOBAL_VALUE (d))
142 d = IDENTIFIER_GLOBAL_VALUE (d);
143 else
145 push_obstacks (&permanent_obstack, &permanent_obstack);
147 type = build_function_type (void_type_node, void_list_node);
148 d = build_lang_decl (FUNCTION_DECL, d, type);
149 DECL_EXTERNAL (d) = 1;
150 TREE_PUBLIC (d) = 1;
151 DECL_ARTIFICIAL (d) = 1;
152 pushdecl_top_level (d);
153 make_function_rtl (d);
154 assemble_external (d);
156 pop_obstacks ();
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 */
166 static tree
167 throw_bad_cast ()
169 return call_void_fn ("__throw_bad_cast");
172 static tree
173 throw_bad_typeid ()
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. */
182 tree
183 get_tinfo_fn_dynamic (exp)
184 tree exp;
186 tree type;
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 exp is a reference to polymorphic type, get the real type_info. */
207 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
209 /* build reference to type_info from vtable. */
210 tree t;
212 if (! flag_rtti)
214 warning ("taking dynamic typeid of object without -frtti");
215 push_obstacks (&permanent_obstack, &permanent_obstack);
216 init_rtti_processing ();
217 pop_obstacks ();
218 flag_rtti = 1;
221 /* If we don't have rtti stuff, get to a sub-object that does. */
222 if (! CLASSTYPE_VFIELDS (type))
224 exp = build_unary_op (ADDR_EXPR, exp, 0);
225 exp = build_headof_sub (exp);
226 exp = build_indirect_ref (exp, NULL_PTR);
229 if (flag_vtable_thunks)
230 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
231 else
232 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
233 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
234 return t;
237 /* otherwise return the type_info for the static type of the expr. */
238 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
241 tree
242 build_typeid (exp)
243 tree exp;
245 exp = get_tinfo_fn_dynamic (exp);
246 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
247 return convert_from_reference (exp);
250 tree
251 build_x_typeid (exp)
252 tree exp;
254 tree cond = NULL_TREE;
255 tree type = TREE_TYPE (tinfo_fn_type);
256 int nonnull;
258 if (processing_template_decl)
259 return build_min_nt (TYPEID_EXPR, exp);
261 if (TREE_CODE (exp) == INDIRECT_REF
262 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
263 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
264 && ! resolves_to_fixed_type_p (exp, &nonnull)
265 && ! nonnull)
267 exp = stabilize_reference (exp);
268 cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
271 exp = get_tinfo_fn_dynamic (exp);
273 if (exp == error_mark_node)
274 return error_mark_node;
276 exp = build_call (exp, type, NULL_TREE);
278 if (cond)
280 tree bad = throw_bad_typeid ();
282 bad = build_compound_expr
283 (expr_tree_cons (NULL_TREE, bad, build_expr_list
284 (NULL_TREE, cp_convert (type, integer_zero_node))));
285 exp = build (COND_EXPR, type, cond, exp, bad);
288 return convert_from_reference (exp);
291 static tree
292 get_tinfo_var (type)
293 tree type;
295 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
296 tree tdecl, arrtype;
297 int size;
299 if (IDENTIFIER_GLOBAL_VALUE (tname))
300 return IDENTIFIER_GLOBAL_VALUE (tname);
302 /* Figure out how much space we need to allocate for the type_info object.
303 If our struct layout or the type_info classes are changed, this will
304 need to be modified. */
305 if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
306 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
307 else if (TREE_CODE (type) == POINTER_TYPE
308 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
309 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
310 size = 3 * POINTER_SIZE;
311 else if (IS_AGGR_TYPE (type))
313 if (CLASSTYPE_N_BASECLASSES (type) == 0)
314 size = 2 * POINTER_SIZE;
315 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
316 && (TREE_VIA_PUBLIC
317 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
318 size = 3 * POINTER_SIZE;
319 else
320 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
322 else
323 size = 2 * POINTER_SIZE;
325 push_obstacks (&permanent_obstack, &permanent_obstack);
327 /* The type for a character array of the appropriate size. */
328 arrtype = build_cplus_array_type
329 (unsigned_char_type_node,
330 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
332 tdecl = build_decl (VAR_DECL, tname, arrtype);
333 TREE_PUBLIC (tdecl) = 1;
334 DECL_EXTERNAL (tdecl) = 1;
335 DECL_ARTIFICIAL (tdecl) = 1;
336 pushdecl_top_level (tdecl);
337 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
339 pop_obstacks ();
341 return tdecl;
344 tree
345 get_tinfo_fn (type)
346 tree type;
348 tree name;
349 tree d;
351 if (TREE_CODE (type) == OFFSET_TYPE)
352 type = TREE_TYPE (type);
353 if (TREE_CODE (type) == METHOD_TYPE)
354 type = build_function_type (TREE_TYPE (type),
355 TREE_CHAIN (TYPE_ARG_TYPES (type)));
357 name = build_overload_with_type (tinfo_fn_id, type);
359 if (IDENTIFIER_GLOBAL_VALUE (name))
360 return IDENTIFIER_GLOBAL_VALUE (name);
362 push_obstacks (&permanent_obstack, &permanent_obstack);
364 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
365 DECL_EXTERNAL (d) = 1;
366 TREE_PUBLIC (d) = 1;
367 DECL_ARTIFICIAL (d) = 1;
368 DECL_NOT_REALLY_EXTERN (d) = 1;
369 DECL_MUTABLE_P (d) = 1;
370 TREE_TYPE (name) = copy_to_permanent (type);
372 pushdecl_top_level (d);
373 make_function_rtl (d);
374 assemble_external (d);
375 mark_inline_for_output (d);
376 if (at_eof)
377 import_export_decl (d);
379 pop_obstacks ();
381 return d;
384 static tree
385 get_typeid_1 (type)
386 tree type;
388 tree t = build_call
389 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
390 return convert_from_reference (t);
393 /* Return the type_info object for TYPE, creating it if necessary. */
395 tree
396 get_typeid (type)
397 tree type;
399 if (type == error_mark_node)
400 return error_mark_node;
402 if (! flag_rtti)
404 warning ("requesting typeid of object without -frtti");
405 push_obstacks (&permanent_obstack, &permanent_obstack);
406 init_rtti_processing ();
407 pop_obstacks ();
408 flag_rtti = 1;
411 if (processing_template_decl)
412 return build_min_nt (TYPEID_EXPR, type);
414 /* If the type of the type-id is a reference type, the result of the
415 typeid expression refers to a type_info object representing the
416 referenced type. */
417 if (TREE_CODE (type) == REFERENCE_TYPE)
418 type = TREE_TYPE (type);
420 /* The top-level cv-qualifiers of the lvalue expression or the type-id
421 that is the operand of typeid are always ignored. */
422 type = TYPE_MAIN_VARIANT (type);
424 return get_typeid_1 (type);
427 /* Check whether TEST is null before returning RESULT. If TEST is used in
428 RESULT, it must have previously had a save_expr applied to it. */
430 static tree
431 ifnonnull (test, result)
432 tree test, result;
434 return build (COND_EXPR, TREE_TYPE (result),
435 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
436 cp_convert (TREE_TYPE (result), integer_zero_node),
437 result);
440 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
441 paper. */
443 static tree
444 build_dynamic_cast_1 (type, expr)
445 tree type, expr;
447 enum tree_code tc = TREE_CODE (type);
448 tree exprtype = TREE_TYPE (expr);
449 enum tree_code ec;
450 tree dcast_fn;
452 assert (exprtype != NULL_TREE);
453 ec = TREE_CODE (exprtype);
455 switch (tc)
457 case POINTER_TYPE:
458 if (ec == REFERENCE_TYPE)
460 expr = convert_from_reference (expr);
461 exprtype = TREE_TYPE (expr);
462 ec = TREE_CODE (exprtype);
464 if (ec != POINTER_TYPE)
465 goto fail;
466 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
467 goto fail;
468 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
469 goto fail;
470 if (TREE_READONLY (TREE_TYPE (exprtype))
471 && ! TYPE_READONLY (TREE_TYPE (type)))
472 goto fail;
473 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
474 break;
475 /* else fall through */
476 case REFERENCE_TYPE:
477 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
478 goto fail;
479 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
480 goto fail;
481 break;
482 /* else fall through */
483 default:
484 goto fail;
487 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
488 if (ec == RECORD_TYPE)
490 exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
491 TREE_THIS_VOLATILE (expr));
492 exprtype = build_reference_type (exprtype);
493 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
494 LOOKUP_NORMAL, NULL_TREE);
495 ec = REFERENCE_TYPE;
498 if (tc == REFERENCE_TYPE)
500 if (ec != REFERENCE_TYPE)
501 goto fail;
502 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
503 goto fail;
504 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
505 goto fail;
506 if (TREE_READONLY (TREE_TYPE (exprtype))
507 && ! TYPE_READONLY (TREE_TYPE (type)))
508 goto fail;
511 /* If *type is an unambiguous accessible base class of *exprtype,
512 convert statically. */
514 int distance;
515 tree path;
517 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
518 &path);
519 if (distance >= 0)
520 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
523 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
524 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
526 tree expr1;
527 /* if TYPE is `void *', return pointer to complete object. */
528 if (tc == POINTER_TYPE
529 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
531 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
532 if (TREE_CODE (expr) == ADDR_EXPR
533 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
534 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
535 return build1 (NOP_EXPR, type, expr);
537 /* Since expr is used twice below, save it. */
538 expr = save_expr (expr);
540 expr1 = build_headof (expr);
541 if (TREE_TYPE (expr1) != type)
542 expr1 = build1 (NOP_EXPR, type, expr1);
543 return ifnonnull (expr, expr1);
545 else
547 tree retval;
548 tree result, td1, td2, td3, elems, expr2;
550 /* If we got here, we can't convert statically. Therefore,
551 dynamic_cast<D&>(b) (b an object) cannot succeed. */
552 if (ec == REFERENCE_TYPE)
554 if (TREE_CODE (expr) == VAR_DECL
555 && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
557 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
558 expr, type);
559 return throw_bad_cast ();
562 /* Ditto for dynamic_cast<D*>(&b). */
563 else if (TREE_CODE (expr) == ADDR_EXPR)
565 tree op = TREE_OPERAND (expr, 0);
566 if (TREE_CODE (op) == VAR_DECL
567 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
569 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
570 expr, type);
571 retval = build_int_2 (0, 0);
572 TREE_TYPE (retval) = type;
573 return retval;
577 /* Since expr is used twice below, save it. */
578 expr = save_expr (expr);
580 expr1 = expr;
581 if (tc == REFERENCE_TYPE)
582 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
584 /* Build run-time conversion. */
585 expr2 = build_headof (expr1);
587 if (ec == POINTER_TYPE)
588 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
589 else
590 td1 = get_tinfo_fn_dynamic (expr);
591 td1 = decay_conversion (td1);
593 td2 = decay_conversion
594 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
595 td3 = decay_conversion
596 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
598 elems = tree_cons
599 (NULL_TREE, td1, tree_cons
600 (NULL_TREE, td2, tree_cons
601 (NULL_TREE, build_int_2 (1, 0), tree_cons
602 (NULL_TREE, expr2, tree_cons
603 (NULL_TREE, td3, tree_cons
604 (NULL_TREE, expr1, NULL_TREE))))));
606 dcast_fn = get_identifier ("__dynamic_cast");
607 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
608 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
609 else
611 tree tmp;
613 push_obstacks (&permanent_obstack, &permanent_obstack);
614 tmp = tree_cons
615 (NULL_TREE, TREE_TYPE (td1), tree_cons
616 (NULL_TREE, TREE_TYPE (td1), tree_cons
617 (NULL_TREE, integer_type_node, tree_cons
618 (NULL_TREE, ptr_type_node, tree_cons
619 (NULL_TREE, TREE_TYPE (td1), tree_cons
620 (NULL_TREE, ptr_type_node, void_list_node))))));
621 tmp = build_function_type (ptr_type_node, tmp);
622 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
623 DECL_EXTERNAL (dcast_fn) = 1;
624 TREE_PUBLIC (dcast_fn) = 1;
625 DECL_ARTIFICIAL (dcast_fn) = 1;
626 pushdecl_top_level (dcast_fn);
627 make_function_rtl (dcast_fn);
628 assemble_external (dcast_fn);
629 pop_obstacks ();
632 result = build_call
633 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
635 if (tc == REFERENCE_TYPE)
637 expr1 = throw_bad_cast ();
638 expr1 = build_compound_expr
639 (expr_tree_cons (NULL_TREE, expr1,
640 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
641 TREE_TYPE (expr1) = type;
642 result = save_expr (result);
643 return build (COND_EXPR, type, result, result, expr1);
646 /* Now back to the type we want from a void*. */
647 result = cp_convert (type, result);
648 return ifnonnull (expr, result);
652 fail:
653 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
654 expr, exprtype, type);
655 return error_mark_node;
658 tree
659 build_dynamic_cast (type, expr)
660 tree type, expr;
662 if (type == error_mark_node || expr == error_mark_node)
663 return error_mark_node;
665 if (processing_template_decl)
666 return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
668 return convert_from_reference (build_dynamic_cast_1 (type, expr));
671 /* Build and initialize various sorts of descriptors. Every descriptor
672 node has a name associated with it (the name created by mangling).
673 For this reason, we use the identifier as our access to the __*_desc
674 nodes, instead of sticking them directly in the types. Otherwise we
675 would burden all built-in types (and pointer types) with slots that
676 we don't necessarily want to use.
678 For each descriptor we build, we build a variable that contains
679 the descriptor's information. When we need this info at runtime,
680 all we need is access to these variables.
682 Note: these constructors always return the address of the descriptor
683 info, since that is simplest for their mutual interaction. */
685 extern tree const_string_type_node;
687 /* Build an initializer for a __si_type_info node. */
689 static void
690 expand_si_desc (tdecl, type)
691 tree tdecl;
692 tree type;
694 tree t, elems, fn;
695 char *name = build_overload_name (type, 1, 1);
696 tree name_string = combine_strings (build_string (strlen (name)+1, name));
698 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
699 expand_expr_stmt (get_typeid_1 (type));
700 t = decay_conversion (get_tinfo_var (type));
701 elems = tree_cons
702 (NULL_TREE, decay_conversion (tdecl), tree_cons
703 (NULL_TREE, decay_conversion (name_string), tree_cons
704 (NULL_TREE, t, NULL_TREE)));
706 fn = get_identifier ("__rtti_si");
707 if (IDENTIFIER_GLOBAL_VALUE (fn))
708 fn = IDENTIFIER_GLOBAL_VALUE (fn);
709 else
711 tree tmp;
712 push_obstacks (&permanent_obstack, &permanent_obstack);
713 tmp = tree_cons
714 (NULL_TREE, ptr_type_node, tree_cons
715 (NULL_TREE, const_string_type_node, tree_cons
716 (NULL_TREE, build_pointer_type (type_info_type_node),
717 void_list_node)));
718 tmp = build_function_type (void_type_node, tmp);
720 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
721 DECL_EXTERNAL (fn) = 1;
722 TREE_PUBLIC (fn) = 1;
723 DECL_ARTIFICIAL (fn) = 1;
724 pushdecl_top_level (fn);
725 make_function_rtl (fn);
726 assemble_external (fn);
727 pop_obstacks ();
730 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
731 expand_expr_stmt (fn);
734 /* Build an initializer for a __class_type_info node. */
736 static void
737 expand_class_desc (tdecl, type)
738 tree tdecl;
739 tree type;
741 tree name_string;
742 tree fn, tmp;
743 char *name;
745 int i = CLASSTYPE_N_BASECLASSES (type);
746 int base_cnt = 0;
747 tree binfos = TYPE_BINFO_BASETYPES (type);
748 #if 0
749 /* See code below that used these. */
750 tree vb = CLASSTYPE_VBASECLASSES (type);
751 int n_base = i;
752 #endif
753 tree base, elems, access, offset, isvir;
754 tree elt, elts = NULL_TREE;
755 static tree base_info_type_node;
757 if (base_info_type_node == NULL_TREE)
759 tree fields [4];
761 /* A reasonably close approximation of __class_type_info::base_info */
763 push_obstacks (&permanent_obstack, &permanent_obstack);
764 base_info_type_node = make_lang_type (RECORD_TYPE);
766 /* Actually const __user_type_info * */
767 fields [0] = build_lang_field_decl
768 (FIELD_DECL, NULL_TREE,
769 build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
770 fields [1] = build_lang_field_decl
771 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
772 DECL_BIT_FIELD (fields[1]) = 1;
773 DECL_FIELD_SIZE (fields[1]) = 29;
775 fields [2] = build_lang_field_decl
776 (FIELD_DECL, NULL_TREE, boolean_type_node);
777 DECL_BIT_FIELD (fields[2]) = 1;
778 DECL_FIELD_SIZE (fields[2]) = 1;
780 /* Actually enum access */
781 fields [3] = build_lang_field_decl
782 (FIELD_DECL, NULL_TREE, integer_type_node);
783 DECL_BIT_FIELD (fields[3]) = 1;
784 DECL_FIELD_SIZE (fields[3]) = 2;
786 finish_builtin_type (base_info_type_node, "__base_info", fields,
787 3, ptr_type_node);
788 pop_obstacks ();
791 while (--i >= 0)
793 tree binfo = TREE_VEC_ELT (binfos, i);
795 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
796 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
798 if (TREE_VIA_VIRTUAL (binfo))
800 tree t = BINFO_TYPE (binfo);
801 char *name;
802 tree field;
804 name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
805 sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
806 field = lookup_field (type, get_identifier (name), 0, 0);
807 offset = size_binop (FLOOR_DIV_EXPR,
808 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
809 offset = convert (sizetype, offset);
811 else
812 offset = BINFO_OFFSET (binfo);
814 if (TREE_VIA_PUBLIC (binfo))
815 access = access_public_node;
816 else if (TREE_VIA_PROTECTED (binfo))
817 access = access_protected_node;
818 else
819 access = access_private_node;
820 if (TREE_VIA_VIRTUAL (binfo))
821 isvir = boolean_true_node;
822 else
823 isvir = boolean_false_node;
825 elt = build
826 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
827 (NULL_TREE, base, tree_cons
828 (NULL_TREE, offset, tree_cons
829 (NULL_TREE, isvir, tree_cons
830 (NULL_TREE, access, NULL_TREE)))));
831 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
832 elts = expr_tree_cons (NULL_TREE, elt, elts);
833 base_cnt++;
835 #if 0
836 i = n_base;
837 while (vb)
839 tree b;
840 access = access_public_node;
841 while (--i >= 0)
843 b = TREE_VEC_ELT (binfos, i);
844 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
846 if (TREE_VIA_PUBLIC (b))
847 access = access_public_node;
848 else if (TREE_VIA_PROTECTED (b))
849 access = access_protected_node;
850 else
851 access = access_private_node;
852 break;
855 base = build_t_desc (BINFO_TYPE (vb), 1);
856 offset = BINFO_OFFSET (vb);
857 isvir = build_int_2 (1, 0);
859 base_list = expr_tree_cons (NULL_TREE, base, base_list);
860 isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
861 acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
862 off_list = expr_tree_cons (NULL_TREE, offset, off_list);
864 base_cnt++;
865 vb = TREE_CHAIN (vb);
867 #endif
869 name = build_overload_name (type, 1, 1);
870 name_string = combine_strings (build_string (strlen (name)+1, name));
873 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
874 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
875 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
876 = TREE_STATIC (elts) = 1;
877 complete_array_type (arrtype, elts, 1);
880 elems = tree_cons
881 (NULL_TREE, decay_conversion (tdecl), tree_cons
882 (NULL_TREE, decay_conversion (name_string), tree_cons
883 (NULL_TREE, decay_conversion (elts), tree_cons
884 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
885 NULL_TREE))));
887 fn = get_identifier ("__rtti_class");
888 if (IDENTIFIER_GLOBAL_VALUE (fn))
889 fn = IDENTIFIER_GLOBAL_VALUE (fn);
890 else
892 push_obstacks (&permanent_obstack, &permanent_obstack);
893 tmp = tree_cons
894 (NULL_TREE, ptr_type_node, tree_cons
895 (NULL_TREE, const_string_type_node, tree_cons
896 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
897 (NULL_TREE, sizetype, void_list_node))));
898 tmp = build_function_type (void_type_node, tmp);
900 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
901 DECL_EXTERNAL (fn) = 1;
902 TREE_PUBLIC (fn) = 1;
903 DECL_ARTIFICIAL (fn) = 1;
904 pushdecl_top_level (fn);
905 make_function_rtl (fn);
906 assemble_external (fn);
907 pop_obstacks ();
910 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
911 expand_expr_stmt (fn);
914 /* Build an initializer for a __pointer_type_info node. */
916 static void
917 expand_ptr_desc (tdecl, type)
918 tree tdecl;
919 tree type;
921 tree t, elems, fn;
922 char *name = build_overload_name (type, 1, 1);
923 tree name_string = combine_strings (build_string (strlen (name)+1, name));
925 type = TREE_TYPE (type);
926 expand_expr_stmt (get_typeid_1 (type));
927 t = decay_conversion (get_tinfo_var (type));
928 elems = tree_cons
929 (NULL_TREE, decay_conversion (tdecl), tree_cons
930 (NULL_TREE, decay_conversion (name_string), tree_cons
931 (NULL_TREE, t, NULL_TREE)));
933 fn = get_identifier ("__rtti_ptr");
934 if (IDENTIFIER_GLOBAL_VALUE (fn))
935 fn = IDENTIFIER_GLOBAL_VALUE (fn);
936 else
938 tree tmp;
939 push_obstacks (&permanent_obstack, &permanent_obstack);
940 tmp = tree_cons
941 (NULL_TREE, ptr_type_node, tree_cons
942 (NULL_TREE, const_string_type_node, tree_cons
943 (NULL_TREE, build_pointer_type (type_info_type_node),
944 void_list_node)));
945 tmp = build_function_type (void_type_node, tmp);
947 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
948 DECL_EXTERNAL (fn) = 1;
949 TREE_PUBLIC (fn) = 1;
950 DECL_ARTIFICIAL (fn) = 1;
951 pushdecl_top_level (fn);
952 make_function_rtl (fn);
953 assemble_external (fn);
954 pop_obstacks ();
957 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
958 expand_expr_stmt (fn);
961 /* Build an initializer for a __attr_type_info node. */
963 static void
964 expand_attr_desc (tdecl, type)
965 tree tdecl;
966 tree type;
968 tree elems, t, fn;
969 char *name = build_overload_name (type, 1, 1);
970 tree name_string = combine_strings (build_string (strlen (name)+1, name));
971 tree attrval = build_int_2
972 (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
974 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
975 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (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, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
981 fn = get_identifier ("__rtti_attr");
982 if (IDENTIFIER_GLOBAL_VALUE (fn))
983 fn = IDENTIFIER_GLOBAL_VALUE (fn);
984 else
986 tree tmp;
987 push_obstacks (&permanent_obstack, &permanent_obstack);
988 tmp = tree_cons
989 (NULL_TREE, ptr_type_node, tree_cons
990 (NULL_TREE, const_string_type_node, tree_cons
991 (NULL_TREE, integer_type_node, tree_cons
992 (NULL_TREE, build_pointer_type (type_info_type_node),
993 void_list_node))));
994 tmp = build_function_type (void_type_node, tmp);
996 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
997 DECL_EXTERNAL (fn) = 1;
998 TREE_PUBLIC (fn) = 1;
999 DECL_ARTIFICIAL (fn) = 1;
1000 pushdecl_top_level (fn);
1001 make_function_rtl (fn);
1002 assemble_external (fn);
1003 pop_obstacks ();
1006 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1007 expand_expr_stmt (fn);
1010 /* Build an initializer for a type_info node that just has a name. */
1012 static void
1013 expand_generic_desc (tdecl, type, fnname)
1014 tree tdecl;
1015 tree type;
1016 char *fnname;
1018 char *name = build_overload_name (type, 1, 1);
1019 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1020 tree elems = tree_cons
1021 (NULL_TREE, decay_conversion (tdecl), tree_cons
1022 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1024 tree fn = get_identifier (fnname);
1025 if (IDENTIFIER_GLOBAL_VALUE (fn))
1026 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1027 else
1029 tree tmp;
1030 push_obstacks (&permanent_obstack, &permanent_obstack);
1031 tmp = tree_cons
1032 (NULL_TREE, ptr_type_node, tree_cons
1033 (NULL_TREE, const_string_type_node, void_list_node));
1034 tmp = build_function_type (void_type_node, tmp);
1036 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1037 DECL_EXTERNAL (fn) = 1;
1038 TREE_PUBLIC (fn) = 1;
1039 DECL_ARTIFICIAL (fn) = 1;
1040 pushdecl_top_level (fn);
1041 make_function_rtl (fn);
1042 assemble_external (fn);
1043 pop_obstacks ();
1046 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1047 expand_expr_stmt (fn);
1050 /* Generate the code for a type_info initialization function.
1051 Note that we take advantage of the passage
1053 5.2.7 Type identification [expr.typeid]
1055 Whether or not the destructor is called for the type_info object at the
1056 end of the program is unspecified.
1058 and don't bother to arrange for these objects to be destroyed. It
1059 doesn't matter, anyway, since the destructors don't do anything.
1061 This must only be called from toplevel (i.e. from finish_file)! */
1063 void
1064 synthesize_tinfo_fn (fndecl)
1065 tree fndecl;
1067 tree type = TREE_TYPE (DECL_NAME (fndecl));
1068 tree tmp, addr;
1070 tree tdecl = get_tinfo_var (type);
1071 DECL_EXTERNAL (tdecl) = 0;
1072 TREE_STATIC (tdecl) = 1;
1073 DECL_COMMON (tdecl) = 1;
1074 TREE_USED (tdecl) = 1;
1075 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1076 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1078 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1079 store_parm_decls ();
1080 clear_last_expr ();
1081 push_momentary ();
1083 /* If the first word of the array (the vtable) is non-zero, we've already
1084 initialized the object, so don't do it again. */
1085 addr = decay_conversion (tdecl);
1086 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1087 tmp = build_indirect_ref (tmp, 0);
1088 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1089 expand_start_cond (tmp, 0);
1091 if (TREE_CODE (type) == FUNCTION_TYPE)
1092 expand_generic_desc (tdecl, type, "__rtti_func");
1093 else if (TREE_CODE (type) == ARRAY_TYPE)
1094 expand_generic_desc (tdecl, type, "__rtti_array");
1095 else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
1096 expand_attr_desc (tdecl, type);
1097 else if (TREE_CODE (type) == POINTER_TYPE)
1099 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1100 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1101 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1102 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1103 else
1104 expand_ptr_desc (tdecl, type);
1106 else if (TYPE_PTRMEMFUNC_P (type))
1107 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1108 else if (IS_AGGR_TYPE (type))
1110 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1111 expand_generic_desc (tdecl, type, "__rtti_user");
1112 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1113 && (TREE_VIA_PUBLIC
1114 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1115 expand_si_desc (tdecl, type);
1116 else
1117 expand_class_desc (tdecl, type);
1119 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1120 expand_generic_desc (tdecl, type, "__rtti_user");
1121 else
1122 my_friendly_abort (252);
1124 expand_end_cond ();
1126 /* OK, now return the type_info object. */
1127 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1128 tmp = build_indirect_ref (tmp, 0);
1129 c_expand_return (tmp);
1130 finish_function (lineno, 0, 0);