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