Warning fixes:
[gcc.git] / gcc / cp / rtti.c
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).
4
5 This file is part of GNU CC.
6
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.
11
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.
16
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. */
21
22
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"
31
32 #ifndef INT_TYPE_SIZE
33 #define INT_TYPE_SIZE BITS_PER_WORD
34 #endif
35
36 extern struct obstack permanent_obstack;
37
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));
51
52 tree type_info_type_node;
53 tree tinfo_fn_id;
54 tree tinfo_fn_type;
55 \f
56 void
57 init_rtti_processing ()
58 {
59 if (flag_honor_std)
60 push_namespace (get_identifier ("std"));
61 type_info_type_node = xref_tag
62 (class_type_node, get_identifier ("type_info"), 1);
63 if (flag_honor_std)
64 pop_namespace ();
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,
68 TYPE_QUAL_CONST)),
69 void_list_node);
70 }
71
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. */
76
77 static tree
78 build_headof_sub (exp)
79 tree exp;
80 {
81 tree type = TREE_TYPE (TREE_TYPE (exp));
82 tree basetype = CLASSTYPE_RTTI (type);
83 tree binfo = get_binfo (basetype, type, 0);
84
85 exp = convert_pointer_to_real (binfo, exp);
86 return exp;
87 }
88
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. */
93
94 static tree
95 build_headof (exp)
96 tree exp;
97 {
98 tree type = TREE_TYPE (exp);
99 tree aref;
100 tree offset;
101
102 if (TREE_CODE (type) != POINTER_TYPE)
103 {
104 error ("`headof' applied to non-pointer type");
105 return error_mark_node;
106 }
107 type = TREE_TYPE (type);
108
109 if (!TYPE_VIRTUAL_P (type))
110 return exp;
111
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);
115
116 /* We use this a couple of times below, protect it. */
117 exp = save_expr (exp);
118
119 aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
120
121 if (flag_vtable_thunks)
122 offset = aref;
123 else
124 offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
125
126 type = build_qualified_type (ptr_type_node,
127 CP_TYPE_QUALS (TREE_TYPE (exp)));
128 return build (PLUS_EXPR, type, exp,
129 cp_convert (ptrdiff_type_node, offset));
130 }
131
132 /* Build a call to a generic entry point taking and returning void. */
133
134 static tree
135 call_void_fn (name)
136 const char *name;
137 {
138 tree d = get_identifier (name);
139 tree type;
140
141 if (IDENTIFIER_GLOBAL_VALUE (d))
142 d = IDENTIFIER_GLOBAL_VALUE (d);
143 else
144 {
145 push_obstacks (&permanent_obstack, &permanent_obstack);
146
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 pop_obstacks ();
155 }
156
157 mark_used (d);
158 return build_call (d, void_type_node, NULL_TREE);
159 }
160
161 /* Get a bad_cast node for the program to throw...
162
163 See libstdc++/exception.cc for __throw_bad_cast */
164
165 static tree
166 throw_bad_cast ()
167 {
168 return call_void_fn ("__throw_bad_cast");
169 }
170
171 static tree
172 throw_bad_typeid ()
173 {
174 return call_void_fn ("__throw_bad_typeid");
175 }
176 \f
177 /* Return the type_info function associated with the expression EXP. If
178 EXP is a reference to a polymorphic class, return the dynamic type;
179 otherwise return the static type of the expression. */
180
181 tree
182 get_tinfo_fn_dynamic (exp)
183 tree exp;
184 {
185 tree type;
186
187 if (exp == error_mark_node)
188 return error_mark_node;
189
190 if (type_unknown_p (exp))
191 {
192 error ("typeid of overloaded function");
193 return error_mark_node;
194 }
195
196 type = TREE_TYPE (exp);
197
198 /* peel back references, so they match. */
199 if (TREE_CODE (type) == REFERENCE_TYPE)
200 type = TREE_TYPE (type);
201
202 /* Peel off cv qualifiers. */
203 type = TYPE_MAIN_VARIANT (type);
204
205 if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
206 {
207 cp_error ("taking typeid of incomplete type `%T'", type);
208 return error_mark_node;
209 }
210
211 /* If exp is a reference to polymorphic type, get the real type_info. */
212 if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
213 {
214 /* build reference to type_info from vtable. */
215 tree t;
216
217 if (! flag_rtti)
218 error ("taking dynamic typeid of object with -fno-rtti");
219
220 /* If we don't have rtti stuff, get to a sub-object that does. */
221 if (! CLASSTYPE_VFIELDS (type))
222 {
223 exp = build_unary_op (ADDR_EXPR, exp, 0);
224 exp = build_headof_sub (exp);
225 exp = build_indirect_ref (exp, NULL_PTR);
226 }
227
228 if (flag_vtable_thunks)
229 t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
230 else
231 t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
232 TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
233 return t;
234 }
235
236 /* otherwise return the type_info for the static type of the expr. */
237 return get_tinfo_fn (TYPE_MAIN_VARIANT (type));
238 }
239
240 tree
241 build_typeid (exp)
242 tree exp;
243 {
244 exp = get_tinfo_fn_dynamic (exp);
245 exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);
246 return convert_from_reference (exp);
247 }
248
249 tree
250 build_x_typeid (exp)
251 tree exp;
252 {
253 tree cond = NULL_TREE;
254 tree type = TREE_TYPE (tinfo_fn_type);
255 int nonnull;
256
257 if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
258 {
259 error ("must #include <typeinfo> before using typeid");
260 return error_mark_node;
261 }
262
263 if (processing_template_decl)
264 return build_min_nt (TYPEID_EXPR, exp);
265
266 if (TREE_CODE (exp) == INDIRECT_REF
267 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
268 && TYPE_VIRTUAL_P (TREE_TYPE (exp))
269 && ! resolves_to_fixed_type_p (exp, &nonnull)
270 && ! nonnull)
271 {
272 exp = stabilize_reference (exp);
273 cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));
274 }
275
276 exp = get_tinfo_fn_dynamic (exp);
277
278 if (exp == error_mark_node)
279 return error_mark_node;
280
281 exp = build_call (exp, type, NULL_TREE);
282
283 if (cond)
284 {
285 tree bad = throw_bad_typeid ();
286
287 bad = build_compound_expr
288 (expr_tree_cons (NULL_TREE, bad, build_expr_list
289 (NULL_TREE, cp_convert (type, integer_zero_node))));
290 exp = build (COND_EXPR, type, cond, exp, bad);
291 }
292
293 return convert_from_reference (exp);
294 }
295
296 static tree
297 get_tinfo_var (type)
298 tree type;
299 {
300 tree tname = build_overload_with_type (get_identifier ("__ti"), type);
301 tree tdecl, arrtype;
302 int size;
303
304 if (IDENTIFIER_GLOBAL_VALUE (tname))
305 return IDENTIFIER_GLOBAL_VALUE (tname);
306
307 /* Figure out how much space we need to allocate for the type_info object.
308 If our struct layout or the type_info classes are changed, this will
309 need to be modified. */
310 if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
311 size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
312 else if (TREE_CODE (type) == POINTER_TYPE
313 && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
314 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
315 size = 3 * POINTER_SIZE;
316 else if (IS_AGGR_TYPE (type))
317 {
318 if (CLASSTYPE_N_BASECLASSES (type) == 0)
319 size = 2 * POINTER_SIZE;
320 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
321 && (TREE_VIA_PUBLIC
322 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
323 size = 3 * POINTER_SIZE;
324 else
325 size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);
326 }
327 else
328 size = 2 * POINTER_SIZE;
329
330 push_obstacks (&permanent_obstack, &permanent_obstack);
331
332 /* The type for a character array of the appropriate size. */
333 arrtype = build_cplus_array_type
334 (unsigned_char_type_node,
335 build_index_type (size_int (size / BITS_PER_UNIT - 1)));
336
337 tdecl = build_decl (VAR_DECL, tname, arrtype);
338 TREE_PUBLIC (tdecl) = 1;
339 DECL_EXTERNAL (tdecl) = 1;
340 DECL_ARTIFICIAL (tdecl) = 1;
341 pushdecl_top_level (tdecl);
342 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
343
344 pop_obstacks ();
345
346 return tdecl;
347 }
348
349 tree
350 get_tinfo_fn (type)
351 tree type;
352 {
353 tree name;
354 tree d;
355
356 if (TREE_CODE (type) == OFFSET_TYPE)
357 type = TREE_TYPE (type);
358 if (TREE_CODE (type) == METHOD_TYPE)
359 type = build_function_type (TREE_TYPE (type),
360 TREE_CHAIN (TYPE_ARG_TYPES (type)));
361
362 name = build_overload_with_type (tinfo_fn_id, type);
363
364 if (IDENTIFIER_GLOBAL_VALUE (name))
365 return IDENTIFIER_GLOBAL_VALUE (name);
366
367 push_obstacks (&permanent_obstack, &permanent_obstack);
368
369 d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
370 DECL_EXTERNAL (d) = 1;
371 TREE_PUBLIC (d) = 1;
372 DECL_ARTIFICIAL (d) = 1;
373 DECL_NOT_REALLY_EXTERN (d) = 1;
374 DECL_MUTABLE_P (d) = 1;
375 TREE_TYPE (name) = copy_to_permanent (type);
376
377 pushdecl_top_level (d);
378 make_function_rtl (d);
379 mark_used (d);
380 mark_inline_for_output (d);
381 pop_obstacks ();
382
383 return d;
384 }
385
386 tree
387 get_typeid_1 (type)
388 tree type;
389 {
390 tree t;
391
392 t = build_call
393 (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
394 return convert_from_reference (t);
395 }
396
397 /* Return the type_info object for TYPE, creating it if necessary. */
398
399 tree
400 get_typeid (type)
401 tree type;
402 {
403 if (type == error_mark_node)
404 return error_mark_node;
405
406 if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
407 {
408 error ("must #include <typeinfo> before using typeid");
409 return error_mark_node;
410 }
411
412 if (! flag_rtti)
413 error ("requesting typeid with -fno-rtti");
414
415 if (processing_template_decl)
416 return build_min_nt (TYPEID_EXPR, type);
417
418 /* If the type of the type-id is a reference type, the result of the
419 typeid expression refers to a type_info object representing the
420 referenced type. */
421 if (TREE_CODE (type) == REFERENCE_TYPE)
422 type = TREE_TYPE (type);
423
424 /* The top-level cv-qualifiers of the lvalue expression or the type-id
425 that is the operand of typeid are always ignored. */
426 type = TYPE_MAIN_VARIANT (type);
427
428 if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
429 {
430 cp_error ("taking typeid of incomplete type `%T'", type);
431 return error_mark_node;
432 }
433
434 return get_typeid_1 (type);
435 }
436
437 /* Check whether TEST is null before returning RESULT. If TEST is used in
438 RESULT, it must have previously had a save_expr applied to it. */
439
440 static tree
441 ifnonnull (test, result)
442 tree test, result;
443 {
444 return build (COND_EXPR, TREE_TYPE (result),
445 build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
446 cp_convert (TREE_TYPE (result), integer_zero_node),
447 result);
448 }
449
450 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
451 paper. */
452
453 static tree
454 build_dynamic_cast_1 (type, expr)
455 tree type, expr;
456 {
457 enum tree_code tc = TREE_CODE (type);
458 tree exprtype;
459 enum tree_code ec;
460 tree dcast_fn;
461 tree old_expr = expr;
462
463 if (TREE_CODE (expr) == OFFSET_REF)
464 expr = resolve_offset_ref (expr);
465
466 exprtype = TREE_TYPE (expr);
467 assert (exprtype != NULL_TREE);
468 ec = TREE_CODE (exprtype);
469
470 switch (tc)
471 {
472 case POINTER_TYPE:
473 if (ec == REFERENCE_TYPE)
474 {
475 expr = convert_from_reference (expr);
476 exprtype = TREE_TYPE (expr);
477 ec = TREE_CODE (exprtype);
478 }
479 if (ec != POINTER_TYPE)
480 goto fail;
481 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
482 goto fail;
483 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
484 goto fail;
485 if (!at_least_as_qualified_p (TREE_TYPE (type),
486 TREE_TYPE (exprtype)))
487 goto fail;
488 if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
489 break;
490 /* else fall through */
491 case REFERENCE_TYPE:
492 if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)
493 goto fail;
494 if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
495 goto fail;
496 break;
497 /* else fall through */
498 default:
499 goto fail;
500 }
501
502 /* Apply trivial conversion T -> T& for dereferenced ptrs. */
503 if (ec == RECORD_TYPE)
504 {
505 exprtype = build_reference_type (exprtype);
506 expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
507 LOOKUP_NORMAL, NULL_TREE);
508 ec = REFERENCE_TYPE;
509 }
510
511 if (tc == REFERENCE_TYPE)
512 {
513 if (ec != REFERENCE_TYPE)
514 goto fail;
515 if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)
516 goto fail;
517 if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
518 goto fail;
519 if (!at_least_as_qualified_p (TREE_TYPE (type),
520 TREE_TYPE (exprtype)))
521 goto fail;
522 }
523
524 /* If *type is an unambiguous accessible base class of *exprtype,
525 convert statically. */
526 {
527 int distance;
528 tree path;
529
530 distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
531 &path);
532
533 if (distance == -2)
534 {
535 cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
536 TREE_TYPE (exprtype), TREE_TYPE (type));
537 return error_mark_node;
538 }
539 if (distance == -3)
540 {
541 cp_error ("dynamic_cast from `%T' to private base class `%T'",
542 TREE_TYPE (exprtype), TREE_TYPE (type));
543 return error_mark_node;
544 }
545
546 if (distance >= 0)
547 return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
548 }
549
550 /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
551 if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
552 {
553 tree expr1;
554 /* if TYPE is `void *', return pointer to complete object. */
555 if (tc == POINTER_TYPE
556 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
557 {
558 /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */
559 if (TREE_CODE (expr) == ADDR_EXPR
560 && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
561 && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
562 return build1 (NOP_EXPR, type, expr);
563
564 /* Since expr is used twice below, save it. */
565 expr = save_expr (expr);
566
567 expr1 = build_headof (expr);
568 if (TREE_TYPE (expr1) != type)
569 expr1 = build1 (NOP_EXPR, type, expr1);
570 return ifnonnull (expr, expr1);
571 }
572 else
573 {
574 tree retval;
575 tree result, td1, td2, td3, elems, expr2;
576
577 /* If we got here, we can't convert statically. Therefore,
578 dynamic_cast<D&>(b) (b an object) cannot succeed. */
579 if (ec == REFERENCE_TYPE)
580 {
581 if (TREE_CODE (old_expr) == VAR_DECL
582 && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
583 {
584 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
585 old_expr, type);
586 return throw_bad_cast ();
587 }
588 }
589 /* Ditto for dynamic_cast<D*>(&b). */
590 else if (TREE_CODE (expr) == ADDR_EXPR)
591 {
592 tree op = TREE_OPERAND (expr, 0);
593 if (TREE_CODE (op) == VAR_DECL
594 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
595 {
596 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
597 op, type);
598 retval = build_int_2 (0, 0);
599 TREE_TYPE (retval) = type;
600 return retval;
601 }
602 }
603
604 /* Since expr is used twice below, save it. */
605 expr = save_expr (expr);
606
607 expr1 = expr;
608 if (tc == REFERENCE_TYPE)
609 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
610
611 /* Build run-time conversion. */
612 expr2 = build_headof (expr1);
613
614 if (ec == POINTER_TYPE)
615 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
616 else
617 td1 = get_tinfo_fn_dynamic (expr);
618 td1 = decay_conversion (td1);
619
620 td2 = decay_conversion
621 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
622 td3 = decay_conversion
623 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
624
625 elems = tree_cons
626 (NULL_TREE, td1, tree_cons
627 (NULL_TREE, td2, tree_cons
628 (NULL_TREE, build_int_2 (1, 0), tree_cons
629 (NULL_TREE, expr2, tree_cons
630 (NULL_TREE, td3, tree_cons
631 (NULL_TREE, expr1, NULL_TREE))))));
632
633 dcast_fn = get_identifier ("__dynamic_cast");
634 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
635 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
636 else
637 {
638 tree tmp;
639
640 push_obstacks (&permanent_obstack, &permanent_obstack);
641 tmp = tree_cons
642 (NULL_TREE, TREE_TYPE (td1), tree_cons
643 (NULL_TREE, TREE_TYPE (td1), tree_cons
644 (NULL_TREE, integer_type_node, tree_cons
645 (NULL_TREE, ptr_type_node, tree_cons
646 (NULL_TREE, TREE_TYPE (td1), tree_cons
647 (NULL_TREE, ptr_type_node, void_list_node))))));
648 tmp = build_function_type (ptr_type_node, tmp);
649 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
650 DECL_EXTERNAL (dcast_fn) = 1;
651 TREE_PUBLIC (dcast_fn) = 1;
652 DECL_ARTIFICIAL (dcast_fn) = 1;
653 pushdecl_top_level (dcast_fn);
654 make_function_rtl (dcast_fn);
655 pop_obstacks ();
656 }
657
658 mark_used (dcast_fn);
659 result = build_call
660 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
661
662 if (tc == REFERENCE_TYPE)
663 {
664 expr1 = throw_bad_cast ();
665 expr1 = build_compound_expr
666 (expr_tree_cons (NULL_TREE, expr1,
667 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
668 TREE_TYPE (expr1) = type;
669 result = save_expr (result);
670 return build (COND_EXPR, type, result, result, expr1);
671 }
672
673 /* Now back to the type we want from a void*. */
674 result = cp_convert (type, result);
675 return ifnonnull (expr, result);
676 }
677 }
678
679 fail:
680 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
681 expr, exprtype, type);
682 return error_mark_node;
683 }
684
685 tree
686 build_dynamic_cast (type, expr)
687 tree type, expr;
688 {
689 if (type == error_mark_node || expr == error_mark_node)
690 return error_mark_node;
691
692 if (processing_template_decl)
693 return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);
694
695 return convert_from_reference (build_dynamic_cast_1 (type, expr));
696 }
697 \f
698 /* Build and initialize various sorts of descriptors. Every descriptor
699 node has a name associated with it (the name created by mangling).
700 For this reason, we use the identifier as our access to the __*_desc
701 nodes, instead of sticking them directly in the types. Otherwise we
702 would burden all built-in types (and pointer types) with slots that
703 we don't necessarily want to use.
704
705 For each descriptor we build, we build a variable that contains
706 the descriptor's information. When we need this info at runtime,
707 all we need is access to these variables.
708
709 Note: these constructors always return the address of the descriptor
710 info, since that is simplest for their mutual interaction. */
711
712 extern tree const_string_type_node;
713
714 /* Build an initializer for a __si_type_info node. */
715
716 static void
717 expand_si_desc (tdecl, type)
718 tree tdecl;
719 tree type;
720 {
721 tree t, elems, fn;
722 const char *name = build_overload_name (type, 1, 1);
723 tree name_string = combine_strings (build_string (strlen (name)+1, name));
724
725 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
726 expand_expr_stmt (get_typeid_1 (type));
727 t = decay_conversion (get_tinfo_var (type));
728 elems = tree_cons
729 (NULL_TREE, decay_conversion (tdecl), tree_cons
730 (NULL_TREE, decay_conversion (name_string), tree_cons
731 (NULL_TREE, t, NULL_TREE)));
732
733 fn = get_identifier ("__rtti_si");
734 if (IDENTIFIER_GLOBAL_VALUE (fn))
735 fn = IDENTIFIER_GLOBAL_VALUE (fn);
736 else
737 {
738 tree tmp;
739 push_obstacks (&permanent_obstack, &permanent_obstack);
740 tmp = tree_cons
741 (NULL_TREE, ptr_type_node, tree_cons
742 (NULL_TREE, const_string_type_node, tree_cons
743 (NULL_TREE, build_pointer_type (type_info_type_node),
744 void_list_node)));
745 tmp = build_function_type (void_type_node, tmp);
746
747 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
748 DECL_EXTERNAL (fn) = 1;
749 TREE_PUBLIC (fn) = 1;
750 DECL_ARTIFICIAL (fn) = 1;
751 pushdecl_top_level (fn);
752 make_function_rtl (fn);
753 pop_obstacks ();
754 }
755
756 mark_used (fn);
757 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
758 expand_expr_stmt (fn);
759 }
760
761 /* Build an initializer for a __class_type_info node. */
762
763 static void
764 expand_class_desc (tdecl, type)
765 tree tdecl;
766 tree type;
767 {
768 tree name_string;
769 tree fn, tmp;
770 const char *name;
771
772 int i = CLASSTYPE_N_BASECLASSES (type);
773 int base_cnt = 0;
774 tree binfos = TYPE_BINFO_BASETYPES (type);
775 #if 0
776 /* See code below that used these. */
777 tree vb = CLASSTYPE_VBASECLASSES (type);
778 int n_base = i;
779 #endif
780 tree base, elems, access, offset, isvir;
781 tree elt, elts = NULL_TREE;
782 static tree base_info_type_node;
783
784 if (base_info_type_node == NULL_TREE)
785 {
786 tree fields [4];
787
788 /* A reasonably close approximation of __class_type_info::base_info */
789
790 push_obstacks (&permanent_obstack, &permanent_obstack);
791 base_info_type_node = make_lang_type (RECORD_TYPE);
792
793 /* Actually const __user_type_info * */
794 fields [0] = build_lang_field_decl
795 (FIELD_DECL, NULL_TREE,
796 build_pointer_type (build_qualified_type
797 (type_info_type_node,
798 TYPE_QUAL_CONST)));
799 fields [1] = build_lang_field_decl
800 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
801 DECL_BIT_FIELD (fields[1]) = 1;
802 DECL_FIELD_SIZE (fields[1]) = 29;
803
804 fields [2] = build_lang_field_decl
805 (FIELD_DECL, NULL_TREE, boolean_type_node);
806 DECL_BIT_FIELD (fields[2]) = 1;
807 DECL_FIELD_SIZE (fields[2]) = 1;
808
809 /* Actually enum access */
810 fields [3] = build_lang_field_decl
811 (FIELD_DECL, NULL_TREE, integer_type_node);
812 DECL_BIT_FIELD (fields[3]) = 1;
813 DECL_FIELD_SIZE (fields[3]) = 2;
814
815 finish_builtin_type (base_info_type_node, "__base_info", fields,
816 3, ptr_type_node);
817 pop_obstacks ();
818 }
819
820 while (--i >= 0)
821 {
822 tree binfo = TREE_VEC_ELT (binfos, i);
823
824 expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
825 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
826
827 if (TREE_VIA_VIRTUAL (binfo))
828 {
829 tree t = BINFO_TYPE (binfo);
830 const char *name;
831 tree field;
832
833 FORMAT_VBASE_NAME (name, t);
834 field = lookup_field (type, get_identifier (name), 0, 0);
835 offset = size_binop (FLOOR_DIV_EXPR,
836 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
837 offset = convert (sizetype, offset);
838 }
839 else
840 offset = BINFO_OFFSET (binfo);
841
842 if (TREE_VIA_PUBLIC (binfo))
843 access = access_public_node;
844 else if (TREE_VIA_PROTECTED (binfo))
845 access = access_protected_node;
846 else
847 access = access_private_node;
848 if (TREE_VIA_VIRTUAL (binfo))
849 isvir = boolean_true_node;
850 else
851 isvir = boolean_false_node;
852
853 elt = build
854 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
855 (NULL_TREE, base, tree_cons
856 (NULL_TREE, offset, tree_cons
857 (NULL_TREE, isvir, tree_cons
858 (NULL_TREE, access, NULL_TREE)))));
859 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
860 elts = expr_tree_cons (NULL_TREE, elt, elts);
861 base_cnt++;
862 }
863 #if 0
864 i = n_base;
865 while (vb)
866 {
867 tree b;
868 access = access_public_node;
869 while (--i >= 0)
870 {
871 b = TREE_VEC_ELT (binfos, i);
872 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
873 {
874 if (TREE_VIA_PUBLIC (b))
875 access = access_public_node;
876 else if (TREE_VIA_PROTECTED (b))
877 access = access_protected_node;
878 else
879 access = access_private_node;
880 break;
881 }
882 }
883 base = build_t_desc (BINFO_TYPE (vb), 1);
884 offset = BINFO_OFFSET (vb);
885 isvir = build_int_2 (1, 0);
886
887 base_list = expr_tree_cons (NULL_TREE, base, base_list);
888 isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list);
889 acc_list = expr_tree_cons (NULL_TREE, access, acc_list);
890 off_list = expr_tree_cons (NULL_TREE, offset, off_list);
891
892 base_cnt++;
893 vb = TREE_CHAIN (vb);
894 }
895 #endif
896
897 name = build_overload_name (type, 1, 1);
898 name_string = combine_strings (build_string (strlen (name)+1, name));
899
900 {
901 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
902 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
903 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
904 = TREE_STATIC (elts) = 1;
905 complete_array_type (arrtype, elts, 1);
906 }
907
908 elems = tree_cons
909 (NULL_TREE, decay_conversion (tdecl), tree_cons
910 (NULL_TREE, decay_conversion (name_string), tree_cons
911 (NULL_TREE, decay_conversion (elts), tree_cons
912 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
913 NULL_TREE))));
914
915 fn = get_identifier ("__rtti_class");
916 if (IDENTIFIER_GLOBAL_VALUE (fn))
917 fn = IDENTIFIER_GLOBAL_VALUE (fn);
918 else
919 {
920 push_obstacks (&permanent_obstack, &permanent_obstack);
921 tmp = tree_cons
922 (NULL_TREE, ptr_type_node, tree_cons
923 (NULL_TREE, const_string_type_node, tree_cons
924 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
925 (NULL_TREE, sizetype, void_list_node))));
926 tmp = build_function_type (void_type_node, tmp);
927
928 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
929 DECL_EXTERNAL (fn) = 1;
930 TREE_PUBLIC (fn) = 1;
931 DECL_ARTIFICIAL (fn) = 1;
932 pushdecl_top_level (fn);
933 make_function_rtl (fn);
934 pop_obstacks ();
935 }
936
937 mark_used (fn);
938 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
939 expand_expr_stmt (fn);
940 }
941
942 /* Build an initializer for a __pointer_type_info node. */
943
944 static void
945 expand_ptr_desc (tdecl, type)
946 tree tdecl;
947 tree type;
948 {
949 tree t, elems, fn;
950 const char *name = build_overload_name (type, 1, 1);
951 tree name_string = combine_strings (build_string (strlen (name)+1, name));
952
953 type = TREE_TYPE (type);
954 expand_expr_stmt (get_typeid_1 (type));
955 t = decay_conversion (get_tinfo_var (type));
956 elems = tree_cons
957 (NULL_TREE, decay_conversion (tdecl), tree_cons
958 (NULL_TREE, decay_conversion (name_string), tree_cons
959 (NULL_TREE, t, NULL_TREE)));
960
961 fn = get_identifier ("__rtti_ptr");
962 if (IDENTIFIER_GLOBAL_VALUE (fn))
963 fn = IDENTIFIER_GLOBAL_VALUE (fn);
964 else
965 {
966 tree tmp;
967 push_obstacks (&permanent_obstack, &permanent_obstack);
968 tmp = tree_cons
969 (NULL_TREE, ptr_type_node, tree_cons
970 (NULL_TREE, const_string_type_node, tree_cons
971 (NULL_TREE, build_pointer_type (type_info_type_node),
972 void_list_node)));
973 tmp = build_function_type (void_type_node, tmp);
974
975 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
976 DECL_EXTERNAL (fn) = 1;
977 TREE_PUBLIC (fn) = 1;
978 DECL_ARTIFICIAL (fn) = 1;
979 pushdecl_top_level (fn);
980 make_function_rtl (fn);
981 pop_obstacks ();
982 }
983
984 mark_used (fn);
985 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
986 expand_expr_stmt (fn);
987 }
988
989 /* Build an initializer for a __attr_type_info node. */
990
991 static void
992 expand_attr_desc (tdecl, type)
993 tree tdecl;
994 tree type;
995 {
996 tree elems, t, fn;
997 const char *name = build_overload_name (type, 1, 1);
998 tree name_string = combine_strings (build_string (strlen (name)+1, name));
999 tree attrval = build_int_2 (TYPE_QUALS (type), 0);
1000
1001 expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
1002 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
1003 elems = tree_cons
1004 (NULL_TREE, decay_conversion (tdecl), tree_cons
1005 (NULL_TREE, decay_conversion (name_string), tree_cons
1006 (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE))));
1007
1008 fn = get_identifier ("__rtti_attr");
1009 if (IDENTIFIER_GLOBAL_VALUE (fn))
1010 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1011 else
1012 {
1013 tree tmp;
1014 push_obstacks (&permanent_obstack, &permanent_obstack);
1015 tmp = tree_cons
1016 (NULL_TREE, ptr_type_node, tree_cons
1017 (NULL_TREE, const_string_type_node, tree_cons
1018 (NULL_TREE, integer_type_node, tree_cons
1019 (NULL_TREE, build_pointer_type (type_info_type_node),
1020 void_list_node))));
1021 tmp = build_function_type (void_type_node, tmp);
1022
1023 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1024 DECL_EXTERNAL (fn) = 1;
1025 TREE_PUBLIC (fn) = 1;
1026 DECL_ARTIFICIAL (fn) = 1;
1027 pushdecl_top_level (fn);
1028 make_function_rtl (fn);
1029 pop_obstacks ();
1030 }
1031
1032 mark_used (fn);
1033 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1034 expand_expr_stmt (fn);
1035 }
1036
1037 /* Build an initializer for a type_info node that just has a name. */
1038
1039 static void
1040 expand_generic_desc (tdecl, type, fnname)
1041 tree tdecl;
1042 tree type;
1043 const char *fnname;
1044 {
1045 const char *name = build_overload_name (type, 1, 1);
1046 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1047 tree elems = tree_cons
1048 (NULL_TREE, decay_conversion (tdecl), tree_cons
1049 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1050
1051 tree fn = get_identifier (fnname);
1052 if (IDENTIFIER_GLOBAL_VALUE (fn))
1053 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1054 else
1055 {
1056 tree tmp;
1057 push_obstacks (&permanent_obstack, &permanent_obstack);
1058 tmp = tree_cons
1059 (NULL_TREE, ptr_type_node, tree_cons
1060 (NULL_TREE, const_string_type_node, void_list_node));
1061 tmp = build_function_type (void_type_node, tmp);
1062
1063 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1064 DECL_EXTERNAL (fn) = 1;
1065 TREE_PUBLIC (fn) = 1;
1066 DECL_ARTIFICIAL (fn) = 1;
1067 pushdecl_top_level (fn);
1068 make_function_rtl (fn);
1069 pop_obstacks ();
1070 }
1071
1072 mark_used (fn);
1073 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1074 expand_expr_stmt (fn);
1075 }
1076
1077 /* Generate the code for a type_info initialization function.
1078 Note that we take advantage of the passage
1079
1080 5.2.7 Type identification [expr.typeid]
1081
1082 Whether or not the destructor is called for the type_info object at the
1083 end of the program is unspecified.
1084
1085 and don't bother to arrange for these objects to be destroyed. It
1086 doesn't matter, anyway, since the destructors don't do anything.
1087
1088 This must only be called from toplevel (i.e. from finish_file)! */
1089
1090 void
1091 synthesize_tinfo_fn (fndecl)
1092 tree fndecl;
1093 {
1094 tree type = TREE_TYPE (DECL_NAME (fndecl));
1095 tree tmp, addr, tdecl;
1096
1097 if (at_eof)
1098 {
1099 import_export_decl (fndecl);
1100 if (DECL_REALLY_EXTERN (fndecl))
1101 return;
1102 }
1103
1104 tdecl = get_tinfo_var (type);
1105 DECL_EXTERNAL (tdecl) = 0;
1106 TREE_STATIC (tdecl) = 1;
1107 DECL_COMMON (tdecl) = 1;
1108 TREE_USED (tdecl) = 1;
1109 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1110 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1111
1112 start_function (NULL_TREE, fndecl, NULL_TREE, 1);
1113 store_parm_decls ();
1114 clear_last_expr ();
1115 push_momentary ();
1116
1117 /* If the first word of the array (the vtable) is non-zero, we've already
1118 initialized the object, so don't do it again. */
1119 addr = decay_conversion (tdecl);
1120 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1121 tmp = build_indirect_ref (tmp, 0);
1122 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
1123 expand_start_cond (tmp, 0);
1124
1125 if (TREE_CODE (type) == FUNCTION_TYPE)
1126 expand_generic_desc (tdecl, type, "__rtti_func");
1127 else if (TREE_CODE (type) == ARRAY_TYPE)
1128 expand_generic_desc (tdecl, type, "__rtti_array");
1129 else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
1130 expand_attr_desc (tdecl, type);
1131 else if (TREE_CODE (type) == POINTER_TYPE)
1132 {
1133 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1134 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1135 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1136 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1137 else
1138 expand_ptr_desc (tdecl, type);
1139 }
1140 else if (TYPE_PTRMEMFUNC_P (type))
1141 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1142 else if (IS_AGGR_TYPE (type))
1143 {
1144 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1145 expand_generic_desc (tdecl, type, "__rtti_user");
1146 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1147 && (TREE_VIA_PUBLIC
1148 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1149 expand_si_desc (tdecl, type);
1150 else
1151 expand_class_desc (tdecl, type);
1152 }
1153 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1154 expand_generic_desc (tdecl, type, "__rtti_user");
1155 else
1156 my_friendly_abort (252);
1157
1158 expand_end_cond ();
1159
1160 /* OK, now return the type_info object. */
1161 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1162 tmp = build_indirect_ref (tmp, 0);
1163 c_expand_return (tmp);
1164 finish_function (lineno, 0, 0);
1165 }