rtti.c (get_tinfo_var): These should always be global
[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
592 /* If we got here, we can't convert statically. Therefore,
593 dynamic_cast<D&>(b) (b an object) cannot succeed. */
594 if (ec == REFERENCE_TYPE)
595 {
596 if (TREE_CODE (old_expr) == VAR_DECL
597 && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
598 {
599 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
600 old_expr, type);
601 return throw_bad_cast ();
602 }
603 }
604 /* Ditto for dynamic_cast<D*>(&b). */
605 else if (TREE_CODE (expr) == ADDR_EXPR)
606 {
607 tree op = TREE_OPERAND (expr, 0);
608 if (TREE_CODE (op) == VAR_DECL
609 && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
610 {
611 cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
612 op, type);
613 retval = build_int_2 (0, 0);
614 TREE_TYPE (retval) = type;
615 return retval;
616 }
617 }
618
619 /* Since expr is used twice below, save it. */
620 expr = save_expr (expr);
621
622 expr1 = expr;
623 if (tc == REFERENCE_TYPE)
624 expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
625
626 /* Build run-time conversion. */
627 expr2 = build_headof (expr1);
628
629 if (ec == POINTER_TYPE)
630 td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));
631 else
632 td1 = get_tinfo_fn_dynamic (expr);
633 td1 = decay_conversion (td1);
634
635 td2 = decay_conversion
636 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));
637 td3 = decay_conversion
638 (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));
639
640 elems = tree_cons
641 (NULL_TREE, td1, tree_cons
642 (NULL_TREE, td2, tree_cons
643 (NULL_TREE, build_int_2 (1, 0), tree_cons
644 (NULL_TREE, expr2, tree_cons
645 (NULL_TREE, td3, tree_cons
646 (NULL_TREE, expr1, NULL_TREE))))));
647
648 dcast_fn = get_identifier ("__dynamic_cast");
649 if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
650 dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
651 else
652 {
653 tree tmp;
654
655 push_obstacks (&permanent_obstack, &permanent_obstack);
656 tmp = tree_cons
657 (NULL_TREE, TREE_TYPE (td1), tree_cons
658 (NULL_TREE, TREE_TYPE (td1), tree_cons
659 (NULL_TREE, integer_type_node, tree_cons
660 (NULL_TREE, ptr_type_node, tree_cons
661 (NULL_TREE, TREE_TYPE (td1), tree_cons
662 (NULL_TREE, ptr_type_node, void_list_node))))));
663 tmp = build_function_type (ptr_type_node, tmp);
664 dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
665 DECL_EXTERNAL (dcast_fn) = 1;
666 TREE_PUBLIC (dcast_fn) = 1;
667 DECL_ARTIFICIAL (dcast_fn) = 1;
668 pushdecl_top_level (dcast_fn);
669 make_function_rtl (dcast_fn);
670 pop_obstacks ();
671 }
672
673 mark_used (dcast_fn);
674 result = build_call
675 (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
676
677 if (tc == REFERENCE_TYPE)
678 {
679 expr1 = throw_bad_cast ();
680 expr1 = build_compound_expr
681 (tree_cons (NULL_TREE, expr1,
682 build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));
683 TREE_TYPE (expr1) = type;
684 result = save_expr (result);
685 return build (COND_EXPR, type, result, result, expr1);
686 }
687
688 /* Now back to the type we want from a void*. */
689 result = cp_convert (type, result);
690 return ifnonnull (expr, result);
691 }
692 }
693
694 fail:
695 cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",
696 expr, exprtype, type);
697 return error_mark_node;
698 }
699
700 tree
701 build_dynamic_cast (type, expr)
702 tree type, expr;
703 {
704 if (type == error_mark_node || expr == error_mark_node)
705 return error_mark_node;
706
707 if (processing_template_decl)
708 return build_min (DYNAMIC_CAST_EXPR, type, expr);
709
710 return convert_from_reference (build_dynamic_cast_1 (type, expr));
711 }
712 \f
713 /* Build and initialize various sorts of descriptors. Every descriptor
714 node has a name associated with it (the name created by mangling).
715 For this reason, we use the identifier as our access to the __*_desc
716 nodes, instead of sticking them directly in the types. Otherwise we
717 would burden all built-in types (and pointer types) with slots that
718 we don't necessarily want to use.
719
720 For each descriptor we build, we build a variable that contains
721 the descriptor's information. When we need this info at runtime,
722 all we need is access to these variables.
723
724 Note: these constructors always return the address of the descriptor
725 info, since that is simplest for their mutual interaction. */
726
727 /* Build an initializer for a __si_type_info node. */
728
729 static void
730 expand_si_desc (tdecl, type)
731 tree tdecl;
732 tree type;
733 {
734 tree t, elems, fn;
735 const char *name = build_overload_name (type, 1, 1);
736 tree name_string = combine_strings (build_string (strlen (name)+1, name));
737
738 type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
739 finish_expr_stmt (get_typeid_1 (type));
740 t = decay_conversion (get_tinfo_var (type));
741 elems = tree_cons
742 (NULL_TREE, decay_conversion (tdecl), tree_cons
743 (NULL_TREE, decay_conversion (name_string), tree_cons
744 (NULL_TREE, t, NULL_TREE)));
745
746 fn = get_identifier ("__rtti_si");
747 if (IDENTIFIER_GLOBAL_VALUE (fn))
748 fn = IDENTIFIER_GLOBAL_VALUE (fn);
749 else
750 {
751 tree tmp;
752 push_obstacks (&permanent_obstack, &permanent_obstack);
753 tmp = tree_cons
754 (NULL_TREE, ptr_type_node, tree_cons
755 (NULL_TREE, const_string_type_node, tree_cons
756 (NULL_TREE, build_pointer_type (type_info_type_node),
757 void_list_node)));
758 tmp = build_function_type (void_type_node, tmp);
759
760 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
761 DECL_EXTERNAL (fn) = 1;
762 TREE_PUBLIC (fn) = 1;
763 DECL_ARTIFICIAL (fn) = 1;
764 pushdecl_top_level (fn);
765 make_function_rtl (fn);
766 pop_obstacks ();
767 }
768
769 mark_used (fn);
770 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
771 finish_expr_stmt (fn);
772 }
773
774 /* Build an initializer for a __class_type_info node. */
775
776 static void
777 expand_class_desc (tdecl, type)
778 tree tdecl;
779 tree type;
780 {
781 tree name_string;
782 tree fn, tmp;
783 const char *name;
784
785 int i = CLASSTYPE_N_BASECLASSES (type);
786 int base_cnt = 0;
787 tree binfos = TYPE_BINFO_BASETYPES (type);
788 #if 0
789 /* See code below that used these. */
790 tree vb = CLASSTYPE_VBASECLASSES (type);
791 int n_base = i;
792 #endif
793 tree base, elems, access, offset, isvir;
794 tree elt, elts = NULL_TREE;
795 static tree base_info_type_node;
796
797 if (base_info_type_node == NULL_TREE)
798 {
799 tree fields [4];
800
801 /* A reasonably close approximation of __class_type_info::base_info */
802
803 push_obstacks (&permanent_obstack, &permanent_obstack);
804 base_info_type_node = make_lang_type (RECORD_TYPE);
805
806 /* Actually const __user_type_info * */
807 fields [0] = build_lang_decl
808 (FIELD_DECL, NULL_TREE,
809 build_pointer_type (build_qualified_type
810 (type_info_type_node,
811 TYPE_QUAL_CONST)));
812 fields [1] = build_lang_decl
813 (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
814 DECL_BIT_FIELD (fields[1]) = 1;
815 DECL_FIELD_SIZE (fields[1]) = 29;
816
817 fields [2] = build_lang_decl
818 (FIELD_DECL, NULL_TREE, boolean_type_node);
819 DECL_BIT_FIELD (fields[2]) = 1;
820 DECL_FIELD_SIZE (fields[2]) = 1;
821
822 /* Actually enum access */
823 fields [3] = build_lang_decl
824 (FIELD_DECL, NULL_TREE, integer_type_node);
825 DECL_BIT_FIELD (fields[3]) = 1;
826 DECL_FIELD_SIZE (fields[3]) = 2;
827
828 finish_builtin_type (base_info_type_node, "__base_info", fields,
829 3, ptr_type_node);
830 pop_obstacks ();
831 }
832
833 while (--i >= 0)
834 {
835 tree binfo = TREE_VEC_ELT (binfos, i);
836
837 finish_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
838 base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
839
840 if (TREE_VIA_VIRTUAL (binfo))
841 {
842 tree t = BINFO_TYPE (binfo);
843 const char *name;
844 tree field;
845
846 FORMAT_VBASE_NAME (name, t);
847 field = lookup_field (type, get_identifier (name), 0, 0);
848 offset = size_binop (FLOOR_DIV_EXPR,
849 DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
850 offset = convert (sizetype, offset);
851 }
852 else
853 offset = BINFO_OFFSET (binfo);
854
855 if (TREE_VIA_PUBLIC (binfo))
856 access = access_public_node;
857 else if (TREE_VIA_PROTECTED (binfo))
858 access = access_protected_node;
859 else
860 access = access_private_node;
861 if (TREE_VIA_VIRTUAL (binfo))
862 isvir = boolean_true_node;
863 else
864 isvir = boolean_false_node;
865
866 elt = build
867 (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
868 (NULL_TREE, base, tree_cons
869 (NULL_TREE, offset, tree_cons
870 (NULL_TREE, isvir, tree_cons
871 (NULL_TREE, access, NULL_TREE)))));
872 TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
873 elts = tree_cons (NULL_TREE, elt, elts);
874 base_cnt++;
875 }
876 #if 0
877 i = n_base;
878 while (vb)
879 {
880 tree b;
881 access = access_public_node;
882 while (--i >= 0)
883 {
884 b = TREE_VEC_ELT (binfos, i);
885 if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
886 {
887 if (TREE_VIA_PUBLIC (b))
888 access = access_public_node;
889 else if (TREE_VIA_PROTECTED (b))
890 access = access_protected_node;
891 else
892 access = access_private_node;
893 break;
894 }
895 }
896 base = build_t_desc (BINFO_TYPE (vb), 1);
897 offset = BINFO_OFFSET (vb);
898 isvir = build_int_2 (1, 0);
899
900 base_list = tree_cons (NULL_TREE, base, base_list);
901 isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
902 acc_list = tree_cons (NULL_TREE, access, acc_list);
903 off_list = tree_cons (NULL_TREE, offset, off_list);
904
905 base_cnt++;
906 vb = TREE_CHAIN (vb);
907 }
908 #endif
909
910 name = build_overload_name (type, 1, 1);
911 name_string = combine_strings (build_string (strlen (name)+1, name));
912
913 {
914 tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
915 elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
916 TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts)
917 = TREE_STATIC (elts) = 1;
918 complete_array_type (arrtype, elts, 1);
919 }
920
921 elems = tree_cons
922 (NULL_TREE, decay_conversion (tdecl), tree_cons
923 (NULL_TREE, decay_conversion (name_string), tree_cons
924 (NULL_TREE, decay_conversion (elts), tree_cons
925 (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)),
926 NULL_TREE))));
927
928 fn = get_identifier ("__rtti_class");
929 if (IDENTIFIER_GLOBAL_VALUE (fn))
930 fn = IDENTIFIER_GLOBAL_VALUE (fn);
931 else
932 {
933 push_obstacks (&permanent_obstack, &permanent_obstack);
934 tmp = tree_cons
935 (NULL_TREE, ptr_type_node, tree_cons
936 (NULL_TREE, const_string_type_node, tree_cons
937 (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
938 (NULL_TREE, sizetype, void_list_node))));
939 tmp = build_function_type (void_type_node, tmp);
940
941 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
942 DECL_EXTERNAL (fn) = 1;
943 TREE_PUBLIC (fn) = 1;
944 DECL_ARTIFICIAL (fn) = 1;
945 pushdecl_top_level (fn);
946 make_function_rtl (fn);
947 pop_obstacks ();
948 }
949
950 mark_used (fn);
951 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
952 finish_expr_stmt (fn);
953 }
954
955 /* Build an initializer for a __pointer_type_info node. */
956
957 static void
958 expand_ptr_desc (tdecl, type)
959 tree tdecl;
960 tree type;
961 {
962 tree t, elems, fn;
963 const char *name = build_overload_name (type, 1, 1);
964 tree name_string = combine_strings (build_string (strlen (name)+1, name));
965
966 type = TREE_TYPE (type);
967 finish_expr_stmt (get_typeid_1 (type));
968 t = decay_conversion (get_tinfo_var (type));
969 elems = tree_cons
970 (NULL_TREE, decay_conversion (tdecl), tree_cons
971 (NULL_TREE, decay_conversion (name_string), tree_cons
972 (NULL_TREE, t, NULL_TREE)));
973
974 fn = get_identifier ("__rtti_ptr");
975 if (IDENTIFIER_GLOBAL_VALUE (fn))
976 fn = IDENTIFIER_GLOBAL_VALUE (fn);
977 else
978 {
979 tree tmp;
980 push_obstacks (&permanent_obstack, &permanent_obstack);
981 tmp = tree_cons
982 (NULL_TREE, ptr_type_node, tree_cons
983 (NULL_TREE, const_string_type_node, tree_cons
984 (NULL_TREE, build_pointer_type (type_info_type_node),
985 void_list_node)));
986 tmp = build_function_type (void_type_node, tmp);
987
988 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
989 DECL_EXTERNAL (fn) = 1;
990 TREE_PUBLIC (fn) = 1;
991 DECL_ARTIFICIAL (fn) = 1;
992 pushdecl_top_level (fn);
993 make_function_rtl (fn);
994 pop_obstacks ();
995 }
996
997 mark_used (fn);
998 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
999 finish_expr_stmt (fn);
1000 }
1001
1002 /* Build an initializer for a __attr_type_info node. */
1003
1004 static void
1005 expand_attr_desc (tdecl, type)
1006 tree tdecl;
1007 tree type;
1008 {
1009 tree elems, t, fn;
1010 const char *name = build_overload_name (type, 1, 1);
1011 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1012 tree attrval = build_int_2 (TYPE_QUALS (type), 0);
1013
1014 finish_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
1015 t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
1016 elems = tree_cons
1017 (NULL_TREE, decay_conversion (tdecl), tree_cons
1018 (NULL_TREE, decay_conversion (name_string), tree_cons
1019 (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
1020
1021 fn = get_identifier ("__rtti_attr");
1022 if (IDENTIFIER_GLOBAL_VALUE (fn))
1023 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1024 else
1025 {
1026 tree tmp;
1027 push_obstacks (&permanent_obstack, &permanent_obstack);
1028 tmp = tree_cons
1029 (NULL_TREE, ptr_type_node, tree_cons
1030 (NULL_TREE, const_string_type_node, tree_cons
1031 (NULL_TREE, integer_type_node, tree_cons
1032 (NULL_TREE, build_pointer_type (type_info_type_node),
1033 void_list_node))));
1034 tmp = build_function_type (void_type_node, tmp);
1035
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 pop_obstacks ();
1043 }
1044
1045 mark_used (fn);
1046 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1047 finish_expr_stmt (fn);
1048 }
1049
1050 /* Build an initializer for a type_info node that just has a name. */
1051
1052 static void
1053 expand_generic_desc (tdecl, type, fnname)
1054 tree tdecl;
1055 tree type;
1056 const char *fnname;
1057 {
1058 const char *name = build_overload_name (type, 1, 1);
1059 tree name_string = combine_strings (build_string (strlen (name)+1, name));
1060 tree elems = tree_cons
1061 (NULL_TREE, decay_conversion (tdecl), tree_cons
1062 (NULL_TREE, decay_conversion (name_string), NULL_TREE));
1063
1064 tree fn = get_identifier (fnname);
1065 if (IDENTIFIER_GLOBAL_VALUE (fn))
1066 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1067 else
1068 {
1069 tree tmp;
1070 push_obstacks (&permanent_obstack, &permanent_obstack);
1071 tmp = tree_cons
1072 (NULL_TREE, ptr_type_node, tree_cons
1073 (NULL_TREE, const_string_type_node, void_list_node));
1074 tmp = build_function_type (void_type_node, tmp);
1075
1076 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1077 DECL_EXTERNAL (fn) = 1;
1078 TREE_PUBLIC (fn) = 1;
1079 DECL_ARTIFICIAL (fn) = 1;
1080 pushdecl_top_level (fn);
1081 make_function_rtl (fn);
1082 pop_obstacks ();
1083 }
1084
1085 mark_used (fn);
1086 fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
1087 finish_expr_stmt (fn);
1088 }
1089
1090 /* Generate the code for a type_info initialization function.
1091 Note that we take advantage of the passage
1092
1093 5.2.7 Type identification [expr.typeid]
1094
1095 Whether or not the destructor is called for the type_info object at the
1096 end of the program is unspecified.
1097
1098 and don't bother to arrange for these objects to be destroyed. It
1099 doesn't matter, anyway, since the destructors don't do anything.
1100
1101 This must only be called from toplevel (i.e. from finish_file)! */
1102
1103 void
1104 synthesize_tinfo_fn (fndecl)
1105 tree fndecl;
1106 {
1107 tree type = TREE_TYPE (DECL_NAME (fndecl));
1108 tree tmp, addr, tdecl;
1109 tree compound_stmt;
1110 tree if_stmt;
1111 tree then_clause;
1112
1113 if (at_eof)
1114 {
1115 import_export_decl (fndecl);
1116 if (DECL_REALLY_EXTERN (fndecl))
1117 return;
1118 }
1119
1120 /* Declare the static typeinfo variable. */
1121 tdecl = get_tinfo_var (type);
1122 DECL_EXTERNAL (tdecl) = 0;
1123 TREE_STATIC (tdecl) = 1;
1124 DECL_COMMON (tdecl) = 1;
1125 TREE_USED (tdecl) = 1;
1126 DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
1127 cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
1128
1129 /* Begin processing the function. */
1130 start_function (NULL_TREE, fndecl, NULL_TREE,
1131 SF_DEFAULT | SF_PRE_PARSED);
1132 store_parm_decls ();
1133 clear_last_expr ();
1134
1135 /* Begin the body of the function. */
1136 compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
1137
1138 /* For convenience, we save away the address of the static
1139 variable. Since we will process expression-statements between
1140 here and the end of the function, we must call push_momentary to
1141 keep ADDR from being overwritten. */
1142 addr = decay_conversion (tdecl);
1143 push_momentary ();
1144
1145 /* If the first word of the array (the vtable) is non-zero, we've already
1146 initialized the object, so don't do it again. */
1147 if_stmt = begin_if_stmt ();
1148 tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
1149 tmp = build_indirect_ref (tmp, 0);
1150 tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node);
1151 finish_if_stmt_cond (tmp, if_stmt);
1152 then_clause = begin_compound_stmt (/*has_no_scope=*/0);
1153
1154 if (TREE_CODE (type) == FUNCTION_TYPE)
1155 expand_generic_desc (tdecl, type, "__rtti_func");
1156 else if (TREE_CODE (type) == ARRAY_TYPE)
1157 expand_generic_desc (tdecl, type, "__rtti_array");
1158 else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
1159 expand_attr_desc (tdecl, type);
1160 else if (TREE_CODE (type) == POINTER_TYPE)
1161 {
1162 if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
1163 expand_generic_desc (tdecl, type, "__rtti_ptmd");
1164 else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
1165 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1166 else
1167 expand_ptr_desc (tdecl, type);
1168 }
1169 else if (TYPE_PTRMEMFUNC_P (type))
1170 expand_generic_desc (tdecl, type, "__rtti_ptmf");
1171 else if (IS_AGGR_TYPE (type))
1172 {
1173 if (CLASSTYPE_N_BASECLASSES (type) == 0)
1174 expand_generic_desc (tdecl, type, "__rtti_user");
1175 else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
1176 && (TREE_VIA_PUBLIC
1177 (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
1178 expand_si_desc (tdecl, type);
1179 else
1180 expand_class_desc (tdecl, type);
1181 }
1182 else if (TREE_CODE (type) == ENUMERAL_TYPE)
1183 expand_generic_desc (tdecl, type, "__rtti_user");
1184 else
1185 my_friendly_abort (252);
1186
1187 finish_compound_stmt (/*has_no_scope=*/0, then_clause);
1188 finish_then_clause (if_stmt);
1189 finish_if_stmt ();
1190
1191 /* OK, now return the type_info object. */
1192 tmp = cp_convert (build_pointer_type (type_info_type_node), addr);
1193 tmp = build_indirect_ref (tmp, 0);
1194 finish_return_stmt (tmp);
1195 /* Undo the call to push_momentary above. */
1196 pop_momentary ();
1197 /* Finish the function body. */
1198 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
1199 finish_function (lineno, 0);
1200 }