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