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