| 1 | /* RunTime Type Identification |
| 2 | Copyright (C) 1995-2025 Free Software Foundation, Inc. |
| 3 | Mostly written by Jason Merrill (jason@cygnus.com). |
| 4 | |
| 5 | This file is part of GCC. |
| 6 | |
| 7 | GCC 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 3, or (at your option) |
| 10 | any later version. |
| 11 | |
| 12 | GCC 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 GCC; see the file COPYING3. If not see |
| 19 | <http://www.gnu.org/licenses/>. */ |
| 20 | |
| 21 | #include "config.h" |
| 22 | #include "system.h" |
| 23 | #include "coretypes.h" |
| 24 | #include "target.h" |
| 25 | #include "cp-tree.h" |
| 26 | #include "memmodel.h" |
| 27 | #include "tm_p.h" |
| 28 | #include "stringpool.h" |
| 29 | #include "intl.h" |
| 30 | #include "stor-layout.h" |
| 31 | #include "c-family/c-pragma.h" |
| 32 | #include "gcc-rich-location.h" |
| 33 | |
| 34 | /* C++ returns type information to the user in struct type_info |
| 35 | objects. We also use type information to implement dynamic_cast and |
| 36 | exception handlers. Type information for a particular type is |
| 37 | indicated with an ABI defined structure derived from type_info. |
| 38 | This would all be very straight forward, but for the fact that the |
| 39 | runtime library provides the definitions of the type_info structure |
| 40 | and the ABI defined derived classes. We cannot build declarations |
| 41 | of them directly in the compiler, but we need to layout objects of |
| 42 | their type. Somewhere we have to lie. |
| 43 | |
| 44 | We define layout compatible POD-structs with compiler-defined names |
| 45 | and generate the appropriate initializations for them (complete |
| 46 | with explicit mention of their vtable). When we have to provide a |
| 47 | type_info to the user we reinterpret_cast the internal compiler |
| 48 | type to type_info. A well formed program can only explicitly refer |
| 49 | to the type_infos of complete types (& cv void). However, we chain |
| 50 | pointer type_infos to the pointed-to-type, and that can be |
| 51 | incomplete. We only need the addresses of such incomplete |
| 52 | type_info objects for static initialization. |
| 53 | |
| 54 | The type information VAR_DECL of a type is held on the |
| 55 | get_global_binding of the type's mangled name. That VAR_DECL |
| 56 | will be the internal type. It will usually have the correct |
| 57 | internal type reflecting the kind of type it represents (pointer, |
| 58 | array, function, class, inherited class, etc). When the type it |
| 59 | represents is incomplete, it will have the internal type |
| 60 | corresponding to type_info. That will only happen at the end of |
| 61 | translation, when we are emitting the type info objects. */ |
| 62 | |
| 63 | /* Auxiliary data we hold for each type_info derived object we need. */ |
| 64 | struct GTY (()) tinfo_s { |
| 65 | tree type; /* The (const-qualified) RECORD_TYPE for this type_info object */ |
| 66 | |
| 67 | tree vtable; /* The VAR_DECL of the vtable. Only filled at end of |
| 68 | translation. */ |
| 69 | |
| 70 | tree name; /* IDENTIFIER_NODE for the ABI specified name of |
| 71 | the type_info derived type. */ |
| 72 | }; |
| 73 | |
| 74 | |
| 75 | enum tinfo_kind |
| 76 | { |
| 77 | TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */ |
| 78 | TK_BASE_TYPE, /* abi::__base_class_type_info */ |
| 79 | TK_DERIVED_TYPES, /* Start of types derived from abi::__type_info */ |
| 80 | TK_BUILTIN_TYPE = TK_DERIVED_TYPES, /* abi::__fundamental_type_info */ |
| 81 | TK_ARRAY_TYPE, /* abi::__array_type_info */ |
| 82 | TK_FUNCTION_TYPE, /* abi::__function_type_info */ |
| 83 | TK_ENUMERAL_TYPE, /* abi::__enum_type_info */ |
| 84 | TK_POINTER_TYPE, /* abi::__pointer_type_info */ |
| 85 | TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */ |
| 86 | TK_CLASS_TYPE, /* abi::__class_type_info */ |
| 87 | TK_SI_CLASS_TYPE, /* abi::__si_class_type_info */ |
| 88 | TK_VMI_CLASS_TYPES, /* abi::__vmi_class_type_info<int> */ |
| 89 | TK_MAX |
| 90 | }; |
| 91 | |
| 92 | /* Names of the tinfo types. Must be same order as TK enumeration |
| 93 | above. */ |
| 94 | |
| 95 | static const char *const tinfo_names[TK_MAX] = |
| 96 | { |
| 97 | "__type_info" , |
| 98 | "__base_class_type_info" , |
| 99 | "__fundamental_type_info" , |
| 100 | "__array_type_info" , |
| 101 | "__function_type_info" , |
| 102 | "__enum_type_info" , |
| 103 | "__pointer_type_info" , |
| 104 | "__pointer_to_member_type_info" , |
| 105 | "__class_type_info" , |
| 106 | "__si_class_type_info" , |
| 107 | "__vmi_class_type_info" |
| 108 | }; |
| 109 | |
| 110 | /* Helper macro to get maximum scalar-width of pointer or of the 'long'-type. |
| 111 | This of interest for llp64 targets. */ |
| 112 | #define LONGPTR_T \ |
| 113 | integer_types[(POINTER_SIZE <= TYPE_PRECISION (integer_types[itk_long]) \ |
| 114 | ? itk_long : itk_long_long)] |
| 115 | |
| 116 | /* A vector of all tinfo decls that haven't yet been emitted. */ |
| 117 | vec<tree, va_gc> *unemitted_tinfo_decls; |
| 118 | |
| 119 | /* A vector of all type_info derived types we need. The first few are |
| 120 | fixed and created early. The remainder are for multiple inheritance |
| 121 | and are generated as needed. */ |
| 122 | static GTY (()) vec<tinfo_s, va_gc> *tinfo_descs; |
| 123 | |
| 124 | static tree tinfo_name (tree, bool); |
| 125 | static tree build_dynamic_cast_1 (location_t, tree, tree, tsubst_flags_t); |
| 126 | static tree throw_bad_cast (void); |
| 127 | static tree throw_bad_typeid (void); |
| 128 | static bool typeid_ok_p (void); |
| 129 | static int qualifier_flags (tree); |
| 130 | static bool target_incomplete_p (tree); |
| 131 | static tree tinfo_base_init (tinfo_s *, tree); |
| 132 | static tree generic_initializer (tinfo_s *, tree); |
| 133 | static tree ptr_initializer (tinfo_s *, tree); |
| 134 | static tree ptm_initializer (tinfo_s *, tree); |
| 135 | static tree class_initializer (tinfo_s *, tree, unsigned, ...); |
| 136 | static tree get_pseudo_ti_init (tree, unsigned); |
| 137 | static unsigned get_pseudo_ti_index (tree); |
| 138 | static tinfo_s *get_tinfo_desc (unsigned); |
| 139 | static void create_tinfo_types (void); |
| 140 | static bool typeinfo_in_lib_p (tree); |
| 141 | |
| 142 | static int doing_runtime = 0; |
| 143 | |
| 144 | /* Create the internal versions of the ABI types. */ |
| 145 | |
| 146 | void |
| 147 | init_rtti_processing (void) |
| 148 | { |
| 149 | vec_alloc (v&: unemitted_tinfo_decls, nelems: 124); |
| 150 | |
| 151 | create_tinfo_types (); |
| 152 | } |
| 153 | |
| 154 | /* Given the expression EXP of type `class *', return the head of the |
| 155 | object pointed to by EXP with type cv void*, if the class has any |
| 156 | virtual functions (TYPE_POLYMORPHIC_P), else just return the |
| 157 | expression. */ |
| 158 | |
| 159 | tree |
| 160 | build_headof (tree exp) |
| 161 | { |
| 162 | tree type = TREE_TYPE (exp); |
| 163 | tree offset; |
| 164 | tree index; |
| 165 | |
| 166 | gcc_assert (TYPE_PTR_P (type)); |
| 167 | type = TREE_TYPE (type); |
| 168 | |
| 169 | if (!TYPE_POLYMORPHIC_P (type)) |
| 170 | return exp; |
| 171 | |
| 172 | /* We use this a couple of times below, protect it. */ |
| 173 | exp = save_expr (exp); |
| 174 | |
| 175 | /* The offset-to-top field is at index -2 from the vptr. */ |
| 176 | index = build_int_cst (NULL_TREE, |
| 177 | -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); |
| 178 | |
| 179 | offset = build_vtbl_ref (cp_build_fold_indirect_ref (exp), |
| 180 | index); |
| 181 | |
| 182 | cp_build_qualified_type (ptr_type_node, |
| 183 | cp_type_quals (TREE_TYPE (exp))); |
| 184 | return fold_build_pointer_plus (exp, offset); |
| 185 | } |
| 186 | |
| 187 | /* Get a bad_cast node for the program to throw... |
| 188 | |
| 189 | See 'libstdc++-v3/libsupc++/eh_aux_runtime.cc' for '__cxa_bad_cast'. */ |
| 190 | |
| 191 | static tree |
| 192 | throw_bad_cast (void) |
| 193 | { |
| 194 | static tree fn; |
| 195 | if (!fn) |
| 196 | { |
| 197 | tree name = get_identifier ("__cxa_bad_cast" ); |
| 198 | fn = get_global_binding (id: name); |
| 199 | if (!fn) |
| 200 | fn = push_throw_library_fn |
| 201 | (name, build_function_type_list (void_type_node, NULL_TREE)); |
| 202 | } |
| 203 | |
| 204 | return build_cxx_call (fn, 0, NULL, tf_warning_or_error); |
| 205 | } |
| 206 | |
| 207 | /* See 'libstdc++-v3/libsupc++/eh_aux_runtime.cc' for '__cxa_bad_typeid'. */ |
| 208 | |
| 209 | static tree |
| 210 | throw_bad_typeid (void) |
| 211 | { |
| 212 | static tree fn; |
| 213 | if (!fn) |
| 214 | { |
| 215 | tree name = get_identifier ("__cxa_bad_typeid" ); |
| 216 | fn = get_global_binding (id: name); |
| 217 | if (!fn) |
| 218 | fn = push_throw_library_fn |
| 219 | (name, build_function_type_list (void_type_node, NULL_TREE)); |
| 220 | } |
| 221 | |
| 222 | return build_cxx_call (fn, 0, NULL, tf_warning_or_error); |
| 223 | } |
| 224 | |
| 225 | /* const type_info*. */ |
| 226 | |
| 227 | inline tree |
| 228 | type_info_ptr_type () |
| 229 | { |
| 230 | return build_pointer_type (const_type_info_type_node); |
| 231 | } |
| 232 | |
| 233 | /* Return a pointer to a type_info object describing TYPE, suitably |
| 234 | cast to the language defined type (for typeid) or void (for building |
| 235 | up the descriptors). */ |
| 236 | |
| 237 | static tree |
| 238 | get_tinfo_ptr (tree type, bool voidp = false) |
| 239 | { |
| 240 | tree decl = get_tinfo_decl (type); |
| 241 | mark_used (decl); |
| 242 | |
| 243 | tree ptype = voidp ? const_ptr_type_node : type_info_ptr_type (); |
| 244 | return build_nop (ptype, build_address (decl)); |
| 245 | } |
| 246 | static inline tree |
| 247 | get_void_tinfo_ptr (tree type) |
| 248 | { |
| 249 | return get_tinfo_ptr (type, voidp: true); |
| 250 | } |
| 251 | |
| 252 | /* Return an lvalue expression whose type is "const std::type_info" |
| 253 | and whose value indicates the type of the expression EXP. If EXP |
| 254 | is a reference to a polymorphic class, return the dynamic type; |
| 255 | otherwise return the static type of the expression. */ |
| 256 | |
| 257 | static tree |
| 258 | get_tinfo_ptr_dynamic (tree exp, tsubst_flags_t complain) |
| 259 | { |
| 260 | tree type; |
| 261 | tree t; |
| 262 | |
| 263 | if (error_operand_p (t: exp)) |
| 264 | return error_mark_node; |
| 265 | |
| 266 | exp = resolve_nondeduced_context (exp, complain); |
| 267 | |
| 268 | /* Peel back references, so they match. */ |
| 269 | type = non_reference (unlowered_expr_type (exp)); |
| 270 | |
| 271 | /* Peel off cv qualifiers. */ |
| 272 | type = cv_unqualified (type); |
| 273 | |
| 274 | /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics. */ |
| 275 | if (CLASS_TYPE_P (type) || type == unknown_type_node |
| 276 | || type == init_list_type_node) |
| 277 | type = complete_type_or_maybe_complain (type, exp, complain); |
| 278 | |
| 279 | if (!type) |
| 280 | return error_mark_node; |
| 281 | |
| 282 | /* If exp is a reference to polymorphic type, get the real type_info. */ |
| 283 | if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0)) |
| 284 | { |
| 285 | /* build reference to type_info from vtable. */ |
| 286 | tree index; |
| 287 | |
| 288 | /* The RTTI information is at index -1. */ |
| 289 | index = build_int_cst (NULL_TREE, |
| 290 | -1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); |
| 291 | t = build_vtbl_ref (exp, index); |
| 292 | t = convert (type_info_ptr_type (), t); |
| 293 | } |
| 294 | else |
| 295 | /* Otherwise return the type_info for the static type of the expr. */ |
| 296 | t = get_tinfo_ptr (type); |
| 297 | |
| 298 | return t; |
| 299 | } |
| 300 | |
| 301 | static bool |
| 302 | typeid_ok_p (void) |
| 303 | { |
| 304 | if (! flag_rtti) |
| 305 | { |
| 306 | error ("cannot use %<typeid%> with %<-fno-rtti%>" ); |
| 307 | return false; |
| 308 | } |
| 309 | |
| 310 | if (!const_type_info_type_node) |
| 311 | { |
| 312 | tree name = get_identifier ("type_info" ); |
| 313 | tree decl = lookup_qualified_name (std_node, name); |
| 314 | if (TREE_CODE (decl) != TYPE_DECL) |
| 315 | { |
| 316 | gcc_rich_location richloc (input_location); |
| 317 | maybe_add_include_fixit (&richloc, "<typeinfo>" , false); |
| 318 | error_at (&richloc, |
| 319 | "must %<#include <typeinfo>%> before using" |
| 320 | " %<typeid%>" ); |
| 321 | |
| 322 | return false; |
| 323 | } |
| 324 | const_type_info_type_node |
| 325 | = cp_build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_CONST); |
| 326 | } |
| 327 | |
| 328 | tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type); |
| 329 | tree real = TYPE_MAIN_VARIANT (const_type_info_type_node); |
| 330 | |
| 331 | /* Make sure abi::__type_info_pseudo has the same alias set |
| 332 | as std::type_info. */ |
| 333 | if (! TYPE_ALIAS_SET_KNOWN_P (pseudo)) |
| 334 | TYPE_ALIAS_SET (pseudo) = get_alias_set (real); |
| 335 | else |
| 336 | gcc_assert (TYPE_ALIAS_SET (pseudo) == get_alias_set (real)); |
| 337 | |
| 338 | return true; |
| 339 | } |
| 340 | |
| 341 | /* Return an expression for "typeid(EXP)". The expression returned is |
| 342 | an lvalue of type "const std::type_info". */ |
| 343 | |
| 344 | tree |
| 345 | build_typeid (tree exp, tsubst_flags_t complain) |
| 346 | { |
| 347 | tree cond = NULL_TREE, initial_expr = exp; |
| 348 | int nonnull = 0; |
| 349 | |
| 350 | if (exp == error_mark_node || !typeid_ok_p ()) |
| 351 | return error_mark_node; |
| 352 | |
| 353 | if (processing_template_decl) |
| 354 | return build_min (TYPEID_EXPR, const_type_info_type_node, exp); |
| 355 | |
| 356 | if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) |
| 357 | && ! resolves_to_fixed_type_p (exp, &nonnull) |
| 358 | && ! nonnull) |
| 359 | { |
| 360 | /* So we need to look into the vtable of the type of exp. |
| 361 | Make sure it isn't a null lvalue. */ |
| 362 | exp = cp_build_addr_expr (exp, complain); |
| 363 | exp = save_expr (exp); |
| 364 | cond = cp_convert (boolean_type_node, exp, complain); |
| 365 | exp = cp_build_fold_indirect_ref (exp); |
| 366 | } |
| 367 | |
| 368 | exp = get_tinfo_ptr_dynamic (exp, complain); |
| 369 | |
| 370 | if (exp == error_mark_node) |
| 371 | return error_mark_node; |
| 372 | |
| 373 | if (cond) |
| 374 | { |
| 375 | tree bad = throw_bad_typeid (); |
| 376 | |
| 377 | exp = build3 (COND_EXPR, TREE_TYPE (exp), cond, exp, bad); |
| 378 | } |
| 379 | else |
| 380 | mark_type_use (initial_expr); |
| 381 | |
| 382 | return cp_build_fold_indirect_ref (exp); |
| 383 | } |
| 384 | |
| 385 | /* Generate the NTBS name of a type. If MARK_PRIVATE, put a '*' in front so that |
| 386 | comparisons will be done by pointer rather than string comparison. */ |
| 387 | static tree |
| 388 | tinfo_name (tree type, bool mark_private) |
| 389 | { |
| 390 | const char *name; |
| 391 | int length; |
| 392 | tree name_string; |
| 393 | |
| 394 | name = mangle_type_string (type); |
| 395 | length = strlen (s: name); |
| 396 | |
| 397 | if (mark_private) |
| 398 | { |
| 399 | /* Inject '*' at beginning of name to force pointer comparison. */ |
| 400 | char* buf = (char*) XALLOCAVEC (char, length + 2); |
| 401 | buf[0] = '*'; |
| 402 | memcpy (dest: buf + 1, src: name, n: length + 1); |
| 403 | name_string = build_string (length + 2, buf); |
| 404 | } |
| 405 | else |
| 406 | name_string = build_string (length + 1, name); |
| 407 | |
| 408 | return fix_string_type (name_string); |
| 409 | } |
| 410 | |
| 411 | /* Return a VAR_DECL for the internal ABI defined type_info object for |
| 412 | TYPE. You must arrange that the decl is mark_used, if actually use |
| 413 | it --- decls in vtables are only used if the vtable is output. */ |
| 414 | |
| 415 | tree |
| 416 | get_tinfo_decl (tree type) |
| 417 | { |
| 418 | if (variably_modified_type_p (type, /*fn=*/NULL_TREE)) |
| 419 | { |
| 420 | error ("cannot create type information for type %qT because " |
| 421 | "it involves types of variable size" , |
| 422 | type); |
| 423 | return error_mark_node; |
| 424 | } |
| 425 | |
| 426 | if (TREE_CODE (type) == METHOD_TYPE) |
| 427 | type = build_function_type (TREE_TYPE (type), |
| 428 | TREE_CHAIN (TYPE_ARG_TYPES (type))); |
| 429 | |
| 430 | return get_tinfo_decl_direct (type, NULL, -1); |
| 431 | } |
| 432 | |
| 433 | /* Get or create a tinfo VAR_DECL directly from the provided information. |
| 434 | The caller must have already checked it is valid to do so. */ |
| 435 | |
| 436 | tree |
| 437 | get_tinfo_decl_direct (tree type, tree name, int pseudo_ix) |
| 438 | { |
| 439 | /* For a class type, the variable is cached in the type node |
| 440 | itself. */ |
| 441 | tree d = NULL_TREE; |
| 442 | |
| 443 | gcc_checking_assert (TREE_CODE (type) != METHOD_TYPE); |
| 444 | |
| 445 | if (CLASS_TYPE_P (type)) |
| 446 | d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)); |
| 447 | |
| 448 | if (!name) |
| 449 | name = mangle_typeinfo_for_type (type); |
| 450 | |
| 451 | if (!CLASS_TYPE_P (type) || TYPE_TRANSPARENT_AGGR (type)) |
| 452 | d = get_global_binding (id: name); |
| 453 | |
| 454 | if (!d) |
| 455 | { |
| 456 | /* Create it. */ |
| 457 | if (pseudo_ix < 0) |
| 458 | pseudo_ix = get_pseudo_ti_index (type); |
| 459 | |
| 460 | const tinfo_s *ti = get_tinfo_desc (pseudo_ix); |
| 461 | |
| 462 | d = build_lang_decl (VAR_DECL, name, ti->type); |
| 463 | SET_DECL_ASSEMBLER_NAME (d, name); |
| 464 | /* Remember the type it is for. */ |
| 465 | TREE_TYPE (name) = type; |
| 466 | DECL_TINFO_P (d) = 1; |
| 467 | DECL_ARTIFICIAL (d) = 1; |
| 468 | DECL_IGNORED_P (d) = 1; |
| 469 | TREE_READONLY (d) = 1; |
| 470 | TREE_STATIC (d) = 1; |
| 471 | TREE_ADDRESSABLE (d) = 1; |
| 472 | /* Tell equal_address_to that different tinfo decls never |
| 473 | overlap. */ |
| 474 | if (vec_safe_is_empty (v: unemitted_tinfo_decls)) |
| 475 | DECL_ATTRIBUTES (d) |
| 476 | = build_tree_list (get_identifier ("non overlapping" ), |
| 477 | NULL_TREE); |
| 478 | else |
| 479 | DECL_ATTRIBUTES (d) |
| 480 | = DECL_ATTRIBUTES ((*unemitted_tinfo_decls)[0]); |
| 481 | |
| 482 | /* Mark the variable as undefined -- but remember that we can |
| 483 | define it later if we need to do so. */ |
| 484 | DECL_EXTERNAL (d) = 1; |
| 485 | DECL_NOT_REALLY_EXTERN (d) = 1; |
| 486 | set_linkage_according_to_type (type, d); |
| 487 | |
| 488 | d = pushdecl_top_level_and_finish (d, NULL_TREE); |
| 489 | if (CLASS_TYPE_P (type)) |
| 490 | CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; |
| 491 | |
| 492 | /* Add decl to the global array of tinfo decls. */ |
| 493 | vec_safe_push (v&: unemitted_tinfo_decls, obj: d); |
| 494 | } |
| 495 | |
| 496 | return d; |
| 497 | } |
| 498 | |
| 499 | /* Return the type_info object for TYPE. */ |
| 500 | |
| 501 | tree |
| 502 | get_typeid (tree type, tsubst_flags_t complain) |
| 503 | { |
| 504 | if (type == error_mark_node || !typeid_ok_p ()) |
| 505 | return error_mark_node; |
| 506 | |
| 507 | if (processing_template_decl) |
| 508 | return build_min (TYPEID_EXPR, const_type_info_type_node, type); |
| 509 | |
| 510 | /* If the type of the type-id is a reference type, the result of the |
| 511 | typeid expression refers to a type_info object representing the |
| 512 | referenced type. */ |
| 513 | type = non_reference (type); |
| 514 | |
| 515 | /* This is not one of the uses of a qualified function type in 8.3.5. */ |
| 516 | if (TREE_CODE (type) == FUNCTION_TYPE |
| 517 | && (type_memfn_quals (type) != TYPE_UNQUALIFIED |
| 518 | || type_memfn_rqual (type) != REF_QUAL_NONE)) |
| 519 | { |
| 520 | if (complain & tf_error) |
| 521 | error ("%<typeid%> of qualified function type %qT" , type); |
| 522 | return error_mark_node; |
| 523 | } |
| 524 | |
| 525 | /* The top-level cv-qualifiers of the lvalue expression or the type-id |
| 526 | that is the operand of typeid are always ignored. */ |
| 527 | type = cv_unqualified (type); |
| 528 | |
| 529 | /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics. */ |
| 530 | if (CLASS_TYPE_P (type) || type == unknown_type_node |
| 531 | || type == init_list_type_node) |
| 532 | type = complete_type_or_maybe_complain (type, NULL_TREE, complain); |
| 533 | |
| 534 | if (!type) |
| 535 | return error_mark_node; |
| 536 | |
| 537 | return cp_build_fold_indirect_ref (get_tinfo_ptr (type)); |
| 538 | } |
| 539 | |
| 540 | /* Check whether TEST is null before returning RESULT. If TEST is used in |
| 541 | RESULT, it must have previously had a save_expr applied to it. */ |
| 542 | |
| 543 | tree |
| 544 | build_if_nonnull (tree test, tree result, tsubst_flags_t complain) |
| 545 | { |
| 546 | tree null_ptr = cp_convert (TREE_TYPE (test), nullptr_node, complain); |
| 547 | tree cond = build2 (NE_EXPR, boolean_type_node, test, null_ptr); |
| 548 | |
| 549 | /* This is a compiler generated comparison, don't emit |
| 550 | e.g. -Wnonnull-compare warning for it. */ |
| 551 | suppress_warning (cond, OPT_Wnonnull); |
| 552 | |
| 553 | null_ptr = cp_convert (TREE_TYPE (result), nullptr_node, complain); |
| 554 | cond = build3 (COND_EXPR, TREE_TYPE (result), cond, result, null_ptr); |
| 555 | |
| 556 | /* Likewise, don't emit -Wnonnull for using the result to call |
| 557 | a member function. */ |
| 558 | suppress_warning (cond, OPT_Wnonnull); |
| 559 | return cond; |
| 560 | } |
| 561 | |
| 562 | /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working |
| 563 | paper. */ |
| 564 | |
| 565 | static tree |
| 566 | build_dynamic_cast_1 (location_t loc, tree type, tree expr, |
| 567 | tsubst_flags_t complain) |
| 568 | { |
| 569 | enum tree_code tc = TREE_CODE (type); |
| 570 | tree exprtype; |
| 571 | tree dcast_fn; |
| 572 | tree old_expr = expr; |
| 573 | const char *errstr = NULL; |
| 574 | |
| 575 | /* Save casted types in the function's used types hash table. */ |
| 576 | used_types_insert (type); |
| 577 | |
| 578 | /* T shall be a pointer or reference to a complete class type, or |
| 579 | `pointer to cv void''. */ |
| 580 | switch (tc) |
| 581 | { |
| 582 | case POINTER_TYPE: |
| 583 | if (VOID_TYPE_P (TREE_TYPE (type))) |
| 584 | break; |
| 585 | /* Fall through. */ |
| 586 | case REFERENCE_TYPE: |
| 587 | if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (type))) |
| 588 | { |
| 589 | errstr = _("target is not pointer or reference to class" ); |
| 590 | goto fail; |
| 591 | } |
| 592 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type)))) |
| 593 | { |
| 594 | errstr = _("target is not pointer or reference to complete type" ); |
| 595 | goto fail; |
| 596 | } |
| 597 | break; |
| 598 | |
| 599 | default: |
| 600 | errstr = _("target is not pointer or reference" ); |
| 601 | goto fail; |
| 602 | } |
| 603 | |
| 604 | if (tc == POINTER_TYPE) |
| 605 | { |
| 606 | expr = decay_conversion (expr, complain); |
| 607 | exprtype = TREE_TYPE (expr); |
| 608 | |
| 609 | /* If T is a pointer type, v shall be an rvalue of a pointer to |
| 610 | complete class type, and the result is an rvalue of type T. */ |
| 611 | |
| 612 | expr = mark_rvalue_use (expr); |
| 613 | |
| 614 | if (!TYPE_PTR_P (exprtype)) |
| 615 | { |
| 616 | errstr = _("source is not a pointer" ); |
| 617 | goto fail; |
| 618 | } |
| 619 | if (! MAYBE_CLASS_TYPE_P (TREE_TYPE (exprtype))) |
| 620 | { |
| 621 | errstr = _("source is not a pointer to class" ); |
| 622 | goto fail; |
| 623 | } |
| 624 | if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (exprtype)))) |
| 625 | { |
| 626 | errstr = _("source is a pointer to incomplete type" ); |
| 627 | goto fail; |
| 628 | } |
| 629 | } |
| 630 | else |
| 631 | { |
| 632 | expr = mark_lvalue_use (expr); |
| 633 | exprtype = TREE_TYPE (expr); |
| 634 | |
| 635 | /* T is a reference type, v shall be an lvalue of a complete class |
| 636 | type, and the result is an lvalue of the type referred to by T. */ |
| 637 | if (! MAYBE_CLASS_TYPE_P (exprtype)) |
| 638 | { |
| 639 | errstr = _("source is not of class type" ); |
| 640 | goto fail; |
| 641 | } |
| 642 | if (!COMPLETE_TYPE_P (complete_type (exprtype))) |
| 643 | { |
| 644 | errstr = _("source is of incomplete class type" ); |
| 645 | goto fail; |
| 646 | } |
| 647 | |
| 648 | exprtype = cp_build_reference_type (exprtype, !lvalue_p (expr)); |
| 649 | } |
| 650 | |
| 651 | /* The dynamic_cast operator shall not cast away constness. */ |
| 652 | if (!at_least_as_qualified_p (TREE_TYPE (type), |
| 653 | TREE_TYPE (exprtype))) |
| 654 | { |
| 655 | errstr = _("conversion casts away constness" ); |
| 656 | goto fail; |
| 657 | } |
| 658 | |
| 659 | /* If *type is an unambiguous accessible base class of *exprtype, |
| 660 | convert statically. */ |
| 661 | { |
| 662 | tree binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type), |
| 663 | ba_check, NULL, complain); |
| 664 | if (binfo) |
| 665 | return build_static_cast (loc, type, expr, complain); |
| 666 | } |
| 667 | |
| 668 | /* Apply trivial conversion T -> T& for dereferenced ptrs. */ |
| 669 | if (tc == REFERENCE_TYPE) |
| 670 | expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, |
| 671 | LOOKUP_NORMAL, NULL_TREE, complain); |
| 672 | |
| 673 | /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ |
| 674 | if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype))) |
| 675 | { |
| 676 | tree expr1; |
| 677 | /* if TYPE is `void *', return pointer to complete object. */ |
| 678 | if (tc == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (type))) |
| 679 | { |
| 680 | /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ |
| 681 | if (TREE_CODE (expr) == ADDR_EXPR |
| 682 | && VAR_P (TREE_OPERAND (expr, 0)) |
| 683 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) |
| 684 | return build1 (NOP_EXPR, type, expr); |
| 685 | |
| 686 | /* Since expr is used twice below, save it. */ |
| 687 | expr = save_expr (expr); |
| 688 | |
| 689 | expr1 = build_headof (exp: expr); |
| 690 | if (TREE_TYPE (expr1) != type) |
| 691 | expr1 = build1 (NOP_EXPR, type, expr1); |
| 692 | return build_if_nonnull (test: expr, result: expr1, complain); |
| 693 | } |
| 694 | else |
| 695 | { |
| 696 | tree retval; |
| 697 | tree result, td2, td3; |
| 698 | tree elems[4]; |
| 699 | tree static_type, target_type, boff; |
| 700 | |
| 701 | /* If we got here, we can't convert statically. Therefore, |
| 702 | dynamic_cast<D&>(b) (b an object) cannot succeed. */ |
| 703 | if (tc == REFERENCE_TYPE) |
| 704 | { |
| 705 | if (VAR_P (old_expr) |
| 706 | && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) |
| 707 | { |
| 708 | tree expr = throw_bad_cast (); |
| 709 | if (complain & tf_warning) |
| 710 | warning_at (loc, 0, |
| 711 | "%<dynamic_cast<%#T>(%#D)%> can never succeed" , |
| 712 | type, old_expr); |
| 713 | /* Bash it to the expected type. */ |
| 714 | TREE_TYPE (expr) = type; |
| 715 | return expr; |
| 716 | } |
| 717 | } |
| 718 | /* Ditto for dynamic_cast<D*>(&b). */ |
| 719 | else if (TREE_CODE (expr) == ADDR_EXPR) |
| 720 | { |
| 721 | tree op = TREE_OPERAND (expr, 0); |
| 722 | if (VAR_P (op) |
| 723 | && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) |
| 724 | { |
| 725 | if (complain & tf_warning) |
| 726 | warning_at (loc, 0, |
| 727 | "%<dynamic_cast<%#T>(%#D)%> can never succeed" , |
| 728 | type, op); |
| 729 | retval = build_int_cst (type, 0); |
| 730 | return retval; |
| 731 | } |
| 732 | } |
| 733 | |
| 734 | /* Use of dynamic_cast when -fno-rtti is prohibited. */ |
| 735 | if (!flag_rtti) |
| 736 | { |
| 737 | if (complain & tf_error) |
| 738 | error_at (loc, |
| 739 | "%<dynamic_cast%> not permitted with %<-fno-rtti%>" ); |
| 740 | return error_mark_node; |
| 741 | } |
| 742 | |
| 743 | target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); |
| 744 | static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); |
| 745 | td2 = get_tinfo_decl (type: target_type); |
| 746 | if (!mark_used (td2, complain) && !(complain & tf_error)) |
| 747 | return error_mark_node; |
| 748 | td2 = cp_build_addr_expr (td2, complain); |
| 749 | td3 = get_tinfo_decl (type: static_type); |
| 750 | if (!mark_used (td3, complain) && !(complain & tf_error)) |
| 751 | return error_mark_node; |
| 752 | td3 = cp_build_addr_expr (td3, complain); |
| 753 | |
| 754 | /* Determine how T and V are related. */ |
| 755 | boff = dcast_base_hint (static_type, target_type); |
| 756 | |
| 757 | /* Since expr is used twice below, save it. */ |
| 758 | expr = save_expr (expr); |
| 759 | |
| 760 | expr1 = expr; |
| 761 | if (tc == REFERENCE_TYPE) |
| 762 | expr1 = cp_build_addr_expr (expr1, complain); |
| 763 | |
| 764 | elems[0] = expr1; |
| 765 | elems[1] = td3; |
| 766 | elems[2] = td2; |
| 767 | elems[3] = boff; |
| 768 | |
| 769 | dcast_fn = dynamic_cast_node; |
| 770 | if (!dcast_fn) |
| 771 | { |
| 772 | unsigned flags = push_abi_namespace (); |
| 773 | tree tinfo_ptr = xref_tag (class_type, |
| 774 | get_identifier ("__class_type_info" )); |
| 775 | tinfo_ptr = cp_build_qualified_type (tinfo_ptr, TYPE_QUAL_CONST); |
| 776 | tinfo_ptr = build_pointer_type (tinfo_ptr); |
| 777 | |
| 778 | const char *fn_name = "__dynamic_cast" ; |
| 779 | /* void *() (void const *, __class_type_info const *, |
| 780 | __class_type_info const *, ptrdiff_t) */ |
| 781 | tree fn_type = (build_function_type_list |
| 782 | (ptr_type_node, const_ptr_type_node, |
| 783 | tinfo_ptr, tinfo_ptr, ptrdiff_type_node, |
| 784 | NULL_TREE)); |
| 785 | dcast_fn = (build_library_fn_ptr |
| 786 | (fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW)); |
| 787 | /* As with __cxa_atexit in get_atexit_node. */ |
| 788 | DECL_CONTEXT (dcast_fn) = FROB_CONTEXT (current_namespace); |
| 789 | DECL_SOURCE_LOCATION (dcast_fn) = BUILTINS_LOCATION; |
| 790 | dcast_fn = pushdecl (dcast_fn, /*hiding=*/true); |
| 791 | pop_abi_namespace (flags); |
| 792 | dynamic_cast_node = dcast_fn; |
| 793 | } |
| 794 | if (dcast_fn == error_mark_node) |
| 795 | return error_mark_node; |
| 796 | result = build_cxx_call (dcast_fn, 4, elems, complain); |
| 797 | SET_EXPR_LOCATION (result, loc); |
| 798 | |
| 799 | if (tc == REFERENCE_TYPE) |
| 800 | { |
| 801 | tree bad = throw_bad_cast (); |
| 802 | tree neq; |
| 803 | |
| 804 | result = save_expr (result); |
| 805 | neq = cp_truthvalue_conversion (result, complain); |
| 806 | return cp_convert (type, |
| 807 | build3 (COND_EXPR, TREE_TYPE (result), |
| 808 | neq, result, bad), complain); |
| 809 | } |
| 810 | |
| 811 | /* Now back to the type we want from a void*. */ |
| 812 | result = cp_convert (type, result, complain); |
| 813 | return build_if_nonnull (test: expr, result, complain); |
| 814 | } |
| 815 | } |
| 816 | else |
| 817 | errstr = _("source type is not polymorphic" ); |
| 818 | |
| 819 | fail: |
| 820 | if (complain & tf_error) |
| 821 | error_at (loc, "cannot %<dynamic_cast%> %qE (of type %q#T) " |
| 822 | "to type %q#T (%s)" , |
| 823 | old_expr, TREE_TYPE (old_expr), type, errstr); |
| 824 | return error_mark_node; |
| 825 | } |
| 826 | |
| 827 | tree |
| 828 | build_dynamic_cast (location_t loc, tree type, tree expr, |
| 829 | tsubst_flags_t complain) |
| 830 | { |
| 831 | tree r; |
| 832 | |
| 833 | if (type == error_mark_node || expr == error_mark_node) |
| 834 | return error_mark_node; |
| 835 | |
| 836 | if (processing_template_decl) |
| 837 | { |
| 838 | expr = build_min (DYNAMIC_CAST_EXPR, type, expr); |
| 839 | TREE_SIDE_EFFECTS (expr) = 1; |
| 840 | r = convert_from_reference (expr); |
| 841 | protected_set_expr_location (r, loc); |
| 842 | return r; |
| 843 | } |
| 844 | |
| 845 | r = convert_from_reference (build_dynamic_cast_1 (loc, type, expr, |
| 846 | complain)); |
| 847 | if (r != error_mark_node) |
| 848 | maybe_warn_about_useless_cast (loc, type, expr, complain); |
| 849 | protected_set_expr_location (r, loc); |
| 850 | return r; |
| 851 | } |
| 852 | |
| 853 | /* Return the runtime bit mask encoding the qualifiers of TYPE. */ |
| 854 | |
| 855 | static int |
| 856 | qualifier_flags (tree type) |
| 857 | { |
| 858 | int flags = 0; |
| 859 | int quals = cp_type_quals (type); |
| 860 | |
| 861 | if (quals & TYPE_QUAL_CONST) |
| 862 | flags |= 1; |
| 863 | if (quals & TYPE_QUAL_VOLATILE) |
| 864 | flags |= 2; |
| 865 | if (quals & TYPE_QUAL_RESTRICT) |
| 866 | flags |= 4; |
| 867 | return flags; |
| 868 | } |
| 869 | |
| 870 | /* Return true, if the pointer chain TYPE ends at an incomplete type, or |
| 871 | contains a pointer to member of an incomplete class. */ |
| 872 | |
| 873 | static bool |
| 874 | target_incomplete_p (tree type) |
| 875 | { |
| 876 | while (true) |
| 877 | if (TYPE_PTRDATAMEM_P (type)) |
| 878 | { |
| 879 | if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))) |
| 880 | return true; |
| 881 | type = TYPE_PTRMEM_POINTED_TO_TYPE (type); |
| 882 | } |
| 883 | else if (TYPE_PTR_P (type)) |
| 884 | type = TREE_TYPE (type); |
| 885 | else |
| 886 | return !COMPLETE_OR_VOID_TYPE_P (type); |
| 887 | } |
| 888 | |
| 889 | /* Returns true if TYPE involves an incomplete class type; in that |
| 890 | case, typeinfo variables for TYPE should be emitted with internal |
| 891 | linkage. */ |
| 892 | |
| 893 | static bool |
| 894 | involves_incomplete_p (tree type) |
| 895 | { |
| 896 | switch (TREE_CODE (type)) |
| 897 | { |
| 898 | case POINTER_TYPE: |
| 899 | return target_incomplete_p (TREE_TYPE (type)); |
| 900 | |
| 901 | case OFFSET_TYPE: |
| 902 | ptrmem: |
| 903 | return |
| 904 | (target_incomplete_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)) |
| 905 | || !COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))); |
| 906 | |
| 907 | case RECORD_TYPE: |
| 908 | if (TYPE_PTRMEMFUNC_P (type)) |
| 909 | goto ptrmem; |
| 910 | /* Fall through. */ |
| 911 | case UNION_TYPE: |
| 912 | if (!COMPLETE_TYPE_P (type)) |
| 913 | return true; |
| 914 | /* Fall through. */ |
| 915 | default: |
| 916 | /* All other types do not involve incomplete class types. */ |
| 917 | return false; |
| 918 | } |
| 919 | } |
| 920 | |
| 921 | /* Return a CONSTRUCTOR for the common part of the type_info objects. This |
| 922 | is the vtable pointer and NTBS name. The NTBS name is emitted as a |
| 923 | comdat const char array, so it becomes a unique key for the type. Generate |
| 924 | and emit that VAR_DECL here. (We can't always emit the type_info itself |
| 925 | as comdat, because of pointers to incomplete.) */ |
| 926 | |
| 927 | static tree |
| 928 | tinfo_base_init (tinfo_s *ti, tree target) |
| 929 | { |
| 930 | tree init; |
| 931 | tree name_decl; |
| 932 | tree vtable_ptr; |
| 933 | vec<constructor_elt, va_gc> *v; |
| 934 | |
| 935 | { |
| 936 | tree name_name, name_string; |
| 937 | |
| 938 | /* Generate the NTBS array variable. */ |
| 939 | tree name_type = build_cplus_array_type |
| 940 | (cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST), |
| 941 | NULL_TREE); |
| 942 | |
| 943 | /* Determine the name of the variable -- and remember with which |
| 944 | type it is associated. */ |
| 945 | name_name = mangle_typeinfo_string_for_type (target); |
| 946 | TREE_TYPE (name_name) = target; |
| 947 | |
| 948 | name_decl = build_lang_decl (VAR_DECL, name_name, name_type); |
| 949 | SET_DECL_ASSEMBLER_NAME (name_decl, name_name); |
| 950 | DECL_ARTIFICIAL (name_decl) = 1; |
| 951 | DECL_IGNORED_P (name_decl) = 1; |
| 952 | TREE_READONLY (name_decl) = 1; |
| 953 | TREE_STATIC (name_decl) = 1; |
| 954 | DECL_EXTERNAL (name_decl) = 0; |
| 955 | DECL_TINFO_P (name_decl) = 1; |
| 956 | set_linkage_according_to_type (target, name_decl); |
| 957 | import_export_decl (name_decl); |
| 958 | name_string = tinfo_name (type: target, mark_private: !TREE_PUBLIC (name_decl)); |
| 959 | DECL_INITIAL (name_decl) = name_string; |
| 960 | mark_used (name_decl); |
| 961 | pushdecl_top_level_and_finish (name_decl, name_string); |
| 962 | } |
| 963 | |
| 964 | vtable_ptr = ti->vtable; |
| 965 | if (!vtable_ptr) |
| 966 | { |
| 967 | int flags = push_abi_namespace (); |
| 968 | tree real_type = xref_tag (class_type, ti->name); |
| 969 | tree real_decl = TYPE_NAME (real_type); |
| 970 | DECL_SOURCE_LOCATION (real_decl) = BUILTINS_LOCATION; |
| 971 | pop_abi_namespace (flags); |
| 972 | |
| 973 | if (!COMPLETE_TYPE_P (real_type)) |
| 974 | { |
| 975 | /* We never saw a definition of this type, so we need to |
| 976 | tell the compiler that this is an exported class, as |
| 977 | indeed all of the __*_type_info classes are. */ |
| 978 | SET_CLASSTYPE_INTERFACE_KNOWN (real_type); |
| 979 | CLASSTYPE_INTERFACE_ONLY (real_type) = 1; |
| 980 | } |
| 981 | |
| 982 | vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); |
| 983 | vtable_ptr = cp_build_addr_expr (vtable_ptr, tf_warning_or_error); |
| 984 | |
| 985 | /* We need to point into the middle of the vtable. */ |
| 986 | vtable_ptr = fold_build_pointer_plus |
| 987 | (vtable_ptr, |
| 988 | size_binop (MULT_EXPR, |
| 989 | size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), |
| 990 | TYPE_SIZE_UNIT (vtable_entry_type))); |
| 991 | |
| 992 | ti->vtable = vtable_ptr; |
| 993 | } |
| 994 | |
| 995 | vec_alloc (v, nelems: 2); |
| 996 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, vtable_ptr); |
| 997 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, |
| 998 | decay_conversion (name_decl, tf_warning_or_error)); |
| 999 | |
| 1000 | init = build_constructor (init_list_type_node, v); |
| 1001 | TREE_CONSTANT (init) = 1; |
| 1002 | TREE_STATIC (init) = 1; |
| 1003 | |
| 1004 | return init; |
| 1005 | } |
| 1006 | |
| 1007 | /* Return the CONSTRUCTOR expr for a type_info of TYPE. TI provides the |
| 1008 | information about the particular type_info derivation, which adds no |
| 1009 | additional fields to the type_info base. */ |
| 1010 | |
| 1011 | static tree |
| 1012 | generic_initializer (tinfo_s *ti, tree target) |
| 1013 | { |
| 1014 | tree init = tinfo_base_init (ti, target); |
| 1015 | |
| 1016 | init = build_constructor_single (init_list_type_node, NULL_TREE, init); |
| 1017 | TREE_CONSTANT (init) = 1; |
| 1018 | TREE_STATIC (init) = 1; |
| 1019 | return init; |
| 1020 | } |
| 1021 | |
| 1022 | /* Return the CONSTRUCTOR expr for a type_info of pointer TYPE. |
| 1023 | TI provides information about the particular type_info derivation, |
| 1024 | which adds target type and qualifier flags members to the type_info base. */ |
| 1025 | |
| 1026 | static tree |
| 1027 | ptr_initializer (tinfo_s *ti, tree target) |
| 1028 | { |
| 1029 | tree init = tinfo_base_init (ti, target); |
| 1030 | tree to = TREE_TYPE (target); |
| 1031 | int flags = qualifier_flags (type: to); |
| 1032 | bool incomplete = target_incomplete_p (type: to); |
| 1033 | vec<constructor_elt, va_gc> *v; |
| 1034 | vec_alloc (v, nelems: 3); |
| 1035 | |
| 1036 | if (incomplete) |
| 1037 | flags |= 8; |
| 1038 | if (tx_safe_fn_type_p (to)) |
| 1039 | { |
| 1040 | flags |= 0x20; |
| 1041 | to = tx_unsafe_fn_variant (to); |
| 1042 | } |
| 1043 | if (flag_noexcept_type |
| 1044 | && FUNC_OR_METHOD_TYPE_P (to) |
| 1045 | && TYPE_NOTHROW_P (to)) |
| 1046 | { |
| 1047 | flags |= 0x40; |
| 1048 | to = build_exception_variant (to, NULL_TREE); |
| 1049 | } |
| 1050 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); |
| 1051 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags)); |
| 1052 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, |
| 1053 | get_void_tinfo_ptr (TYPE_MAIN_VARIANT (to))); |
| 1054 | |
| 1055 | init = build_constructor (init_list_type_node, v); |
| 1056 | TREE_CONSTANT (init) = 1; |
| 1057 | TREE_STATIC (init) = 1; |
| 1058 | return init; |
| 1059 | } |
| 1060 | |
| 1061 | /* Return the CONSTRUCTOR expr for a type_info of pointer to member data TYPE. |
| 1062 | TI provides information about the particular type_info derivation, |
| 1063 | which adds class, target type and qualifier flags members to the type_info |
| 1064 | base. */ |
| 1065 | |
| 1066 | static tree |
| 1067 | ptm_initializer (tinfo_s *ti, tree target) |
| 1068 | { |
| 1069 | tree init = tinfo_base_init (ti, target); |
| 1070 | tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target); |
| 1071 | tree klass = TYPE_PTRMEM_CLASS_TYPE (target); |
| 1072 | int flags = qualifier_flags (type: to); |
| 1073 | bool incomplete = target_incomplete_p (type: to); |
| 1074 | vec<constructor_elt, va_gc> *v; |
| 1075 | vec_alloc (v, nelems: 4); |
| 1076 | |
| 1077 | if (incomplete) |
| 1078 | flags |= 0x8; |
| 1079 | if (!COMPLETE_TYPE_P (klass)) |
| 1080 | flags |= 0x10; |
| 1081 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); |
| 1082 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags)); |
| 1083 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, |
| 1084 | get_void_tinfo_ptr (TYPE_MAIN_VARIANT (to))); |
| 1085 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, get_void_tinfo_ptr (klass)); |
| 1086 | |
| 1087 | init = build_constructor (init_list_type_node, v); |
| 1088 | TREE_CONSTANT (init) = 1; |
| 1089 | TREE_STATIC (init) = 1; |
| 1090 | return init; |
| 1091 | } |
| 1092 | |
| 1093 | /* Return the CONSTRUCTOR expr for a type_info of class TYPE. |
| 1094 | TI provides information about the particular __class_type_info derivation, |
| 1095 | which adds hint flags and N extra initializers to the type_info base. */ |
| 1096 | |
| 1097 | static tree |
| 1098 | class_initializer (tinfo_s *ti, tree target, unsigned n, ...) |
| 1099 | { |
| 1100 | tree init = tinfo_base_init (ti, target); |
| 1101 | va_list ; |
| 1102 | unsigned i; |
| 1103 | vec<constructor_elt, va_gc> *v; |
| 1104 | vec_alloc (v, nelems: n+1); |
| 1105 | |
| 1106 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); |
| 1107 | va_start (extra_inits, n); |
| 1108 | for (i = 0; i < n; i++) |
| 1109 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, va_arg (extra_inits, tree)); |
| 1110 | va_end (extra_inits); |
| 1111 | |
| 1112 | init = build_constructor (init_list_type_node, v); |
| 1113 | TREE_CONSTANT (init) = 1; |
| 1114 | TREE_STATIC (init) = 1; |
| 1115 | return init; |
| 1116 | } |
| 1117 | |
| 1118 | /* Returns true if the typeinfo for type should be placed in |
| 1119 | the runtime library. */ |
| 1120 | |
| 1121 | static bool |
| 1122 | typeinfo_in_lib_p (tree type) |
| 1123 | { |
| 1124 | /* The typeinfo objects for `T*' and `const T*' are in the runtime |
| 1125 | library for simple types T. */ |
| 1126 | if (TYPE_PTR_P (type) |
| 1127 | && (cp_type_quals (TREE_TYPE (type)) == TYPE_QUAL_CONST |
| 1128 | || cp_type_quals (TREE_TYPE (type)) == TYPE_UNQUALIFIED)) |
| 1129 | type = TREE_TYPE (type); |
| 1130 | |
| 1131 | switch (TREE_CODE (type)) |
| 1132 | { |
| 1133 | case INTEGER_TYPE: |
| 1134 | case BOOLEAN_TYPE: |
| 1135 | case REAL_TYPE: |
| 1136 | case VOID_TYPE: |
| 1137 | case NULLPTR_TYPE: |
| 1138 | return true; |
| 1139 | |
| 1140 | case LANG_TYPE: |
| 1141 | /* fall through. */ |
| 1142 | |
| 1143 | default: |
| 1144 | return false; |
| 1145 | } |
| 1146 | } |
| 1147 | |
| 1148 | /* Generate the initializer for the type info describing TYPE. TK_INDEX is |
| 1149 | the index of the descriptor in the tinfo_desc vector. */ |
| 1150 | |
| 1151 | static tree |
| 1152 | get_pseudo_ti_init (tree type, unsigned tk_index) |
| 1153 | { |
| 1154 | tinfo_s *ti = get_tinfo_desc (tk_index); |
| 1155 | |
| 1156 | gcc_assert (at_eof); |
| 1157 | switch (tk_index) |
| 1158 | { |
| 1159 | case TK_POINTER_MEMBER_TYPE: |
| 1160 | return ptm_initializer (ti, target: type); |
| 1161 | |
| 1162 | case TK_POINTER_TYPE: |
| 1163 | return ptr_initializer (ti, target: type); |
| 1164 | |
| 1165 | case TK_BUILTIN_TYPE: |
| 1166 | case TK_ENUMERAL_TYPE: |
| 1167 | case TK_FUNCTION_TYPE: |
| 1168 | case TK_ARRAY_TYPE: |
| 1169 | return generic_initializer (ti, target: type); |
| 1170 | |
| 1171 | case TK_CLASS_TYPE: |
| 1172 | return class_initializer (ti, target: type, n: 0); |
| 1173 | |
| 1174 | case TK_SI_CLASS_TYPE: |
| 1175 | { |
| 1176 | tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0); |
| 1177 | tree tinfo = get_void_tinfo_ptr (BINFO_TYPE (base_binfo)); |
| 1178 | |
| 1179 | /* get_tinfo_ptr might have reallocated the tinfo_descs vector. */ |
| 1180 | ti = &(*tinfo_descs)[tk_index]; |
| 1181 | return class_initializer (ti, target: type, n: 1, tinfo); |
| 1182 | } |
| 1183 | |
| 1184 | default: |
| 1185 | { |
| 1186 | int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0) |
| 1187 | | (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1)); |
| 1188 | tree binfo = TYPE_BINFO (type); |
| 1189 | unsigned nbases = BINFO_N_BASE_BINFOS (binfo); |
| 1190 | vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo); |
| 1191 | tree offset_type = LONGPTR_T; |
| 1192 | vec<constructor_elt, va_gc> *init_vec = NULL; |
| 1193 | |
| 1194 | gcc_assert (tk_index - TK_VMI_CLASS_TYPES + 1 == nbases); |
| 1195 | |
| 1196 | vec_safe_grow (v&: init_vec, len: nbases, exact: true); |
| 1197 | /* Generate the base information initializer. */ |
| 1198 | for (unsigned ix = nbases; ix--;) |
| 1199 | { |
| 1200 | tree base_binfo = BINFO_BASE_BINFO (binfo, ix); |
| 1201 | int flags = 0; |
| 1202 | tree tinfo; |
| 1203 | tree offset; |
| 1204 | vec<constructor_elt, va_gc> *v; |
| 1205 | |
| 1206 | if ((*base_accesses)[ix] == access_public_node) |
| 1207 | flags |= 2; |
| 1208 | tinfo = get_void_tinfo_ptr (BINFO_TYPE (base_binfo)); |
| 1209 | if (BINFO_VIRTUAL_P (base_binfo)) |
| 1210 | { |
| 1211 | /* We store the vtable offset at which the virtual |
| 1212 | base offset can be found. */ |
| 1213 | offset = BINFO_VPTR_FIELD (base_binfo); |
| 1214 | flags |= 1; |
| 1215 | } |
| 1216 | else |
| 1217 | offset = BINFO_OFFSET (base_binfo); |
| 1218 | |
| 1219 | /* Combine offset and flags into one field. */ |
| 1220 | offset = fold_convert (offset_type, offset); |
| 1221 | offset = fold_build2_loc (input_location, |
| 1222 | LSHIFT_EXPR, offset_type, offset, |
| 1223 | build_int_cst (offset_type, 8)); |
| 1224 | offset = fold_build2_loc (input_location, |
| 1225 | BIT_IOR_EXPR, offset_type, offset, |
| 1226 | build_int_cst (offset_type, flags)); |
| 1227 | vec_alloc (v, nelems: 2); |
| 1228 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo); |
| 1229 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset); |
| 1230 | tree base_init = build_constructor (init_list_type_node, v); |
| 1231 | constructor_elt *e = &(*init_vec)[ix]; |
| 1232 | e->index = NULL_TREE; |
| 1233 | e->value = base_init; |
| 1234 | } |
| 1235 | tree base_inits = build_constructor (init_list_type_node, init_vec); |
| 1236 | |
| 1237 | /* get_tinfo_ptr might have reallocated the tinfo_descs vector. */ |
| 1238 | ti = &(*tinfo_descs)[tk_index]; |
| 1239 | return class_initializer (ti, target: type, n: 3, |
| 1240 | build_int_cst (NULL_TREE, hint), |
| 1241 | build_int_cst (NULL_TREE, nbases), |
| 1242 | base_inits); |
| 1243 | } |
| 1244 | } |
| 1245 | } |
| 1246 | |
| 1247 | /* Return the index of a pseudo type info type node used to describe |
| 1248 | TYPE. TYPE must be a complete type (or cv void), except at the end |
| 1249 | of the translation unit. */ |
| 1250 | |
| 1251 | static unsigned |
| 1252 | get_pseudo_ti_index (tree type) |
| 1253 | { |
| 1254 | unsigned ix; |
| 1255 | |
| 1256 | switch (TREE_CODE (type)) |
| 1257 | { |
| 1258 | case OFFSET_TYPE: |
| 1259 | ix = TK_POINTER_MEMBER_TYPE; |
| 1260 | break; |
| 1261 | |
| 1262 | case POINTER_TYPE: |
| 1263 | ix = TK_POINTER_TYPE; |
| 1264 | break; |
| 1265 | |
| 1266 | case ENUMERAL_TYPE: |
| 1267 | ix = TK_ENUMERAL_TYPE; |
| 1268 | break; |
| 1269 | |
| 1270 | case FUNCTION_TYPE: |
| 1271 | ix = TK_FUNCTION_TYPE; |
| 1272 | break; |
| 1273 | |
| 1274 | case ARRAY_TYPE: |
| 1275 | ix = TK_ARRAY_TYPE; |
| 1276 | break; |
| 1277 | |
| 1278 | case UNION_TYPE: |
| 1279 | case RECORD_TYPE: |
| 1280 | if (TYPE_PTRMEMFUNC_P (type)) |
| 1281 | ix = TK_POINTER_MEMBER_TYPE; |
| 1282 | else if (!COMPLETE_TYPE_P (type)) |
| 1283 | { |
| 1284 | if (!at_eof) |
| 1285 | cxx_incomplete_type_error (NULL_TREE, type); |
| 1286 | ix = TK_CLASS_TYPE; |
| 1287 | } |
| 1288 | else if (!TYPE_BINFO (type) |
| 1289 | || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))) |
| 1290 | ix = TK_CLASS_TYPE; |
| 1291 | else |
| 1292 | { |
| 1293 | tree binfo = TYPE_BINFO (type); |
| 1294 | vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo); |
| 1295 | tree base_binfo = BINFO_BASE_BINFO (binfo, 0); |
| 1296 | int num_bases = BINFO_N_BASE_BINFOS (binfo); |
| 1297 | |
| 1298 | if (num_bases == 1 |
| 1299 | && (*base_accesses)[0] == access_public_node |
| 1300 | && !BINFO_VIRTUAL_P (base_binfo) |
| 1301 | && integer_zerop (BINFO_OFFSET (base_binfo))) |
| 1302 | /* single non-virtual public. */ |
| 1303 | ix = TK_SI_CLASS_TYPE; |
| 1304 | else |
| 1305 | ix = TK_VMI_CLASS_TYPES + num_bases - 1; |
| 1306 | } |
| 1307 | break; |
| 1308 | |
| 1309 | default: |
| 1310 | ix = TK_BUILTIN_TYPE; |
| 1311 | break; |
| 1312 | } |
| 1313 | return ix; |
| 1314 | } |
| 1315 | |
| 1316 | /* Return pointer to tinfo descriptor. Possibly creating the tinfo |
| 1317 | descriptor in the first place. */ |
| 1318 | |
| 1319 | static tinfo_s * |
| 1320 | get_tinfo_desc (unsigned ix) |
| 1321 | { |
| 1322 | if (tinfo_descs->length () <= ix) |
| 1323 | /* too short, extend. */ |
| 1324 | vec_safe_grow_cleared (v&: tinfo_descs, len: ix + 1); |
| 1325 | |
| 1326 | tinfo_s *res = &(*tinfo_descs)[ix]; |
| 1327 | |
| 1328 | if (res->type) |
| 1329 | return res; |
| 1330 | |
| 1331 | /* Ok, we have to create it. This layout must be consistent with |
| 1332 | that defined in the runtime support. We explicitly manage the |
| 1333 | vtable member, and name it for real type as used in the runtime. |
| 1334 | The RECORD type has a different name, to avoid collisions. We |
| 1335 | have to delay generating the VAR_DECL of the vtable until the end |
| 1336 | of the translation, when we'll have seen the library definition, |
| 1337 | if there was one. */ |
| 1338 | |
| 1339 | /* Fields to add, chained in reverse order. */ |
| 1340 | tree fields = NULL_TREE; |
| 1341 | |
| 1342 | if (ix >= TK_DERIVED_TYPES) |
| 1343 | { |
| 1344 | /* First field is the pseudo type_info base class. */ |
| 1345 | tree fld_base = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, |
| 1346 | get_tinfo_desc (ix: TK_TYPE_INFO_TYPE)->type); |
| 1347 | |
| 1348 | DECL_CHAIN (fld_base) = fields; |
| 1349 | fields = fld_base; |
| 1350 | } |
| 1351 | |
| 1352 | switch (ix) |
| 1353 | { |
| 1354 | case TK_TYPE_INFO_TYPE: |
| 1355 | { |
| 1356 | tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1357 | NULL_TREE, const_ptr_type_node); |
| 1358 | fields = fld_ptr; |
| 1359 | |
| 1360 | tree fld_str = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1361 | NULL_TREE, const_string_type_node); |
| 1362 | DECL_CHAIN (fld_str) = fields; |
| 1363 | fields = fld_str; |
| 1364 | break; |
| 1365 | } |
| 1366 | |
| 1367 | case TK_BASE_TYPE: |
| 1368 | { |
| 1369 | /* Base class internal helper. Pointer to base type, offset to |
| 1370 | base, flags. */ |
| 1371 | tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1372 | NULL_TREE, const_ptr_type_node); |
| 1373 | DECL_CHAIN (fld_ptr) = fields; |
| 1374 | fields = fld_ptr; |
| 1375 | |
| 1376 | tree fld_flag = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1377 | NULL_TREE, LONGPTR_T); |
| 1378 | DECL_CHAIN (fld_flag) = fields; |
| 1379 | fields = fld_flag; |
| 1380 | break; |
| 1381 | } |
| 1382 | |
| 1383 | case TK_BUILTIN_TYPE: |
| 1384 | /* Fundamental type_info */ |
| 1385 | break; |
| 1386 | |
| 1387 | case TK_ARRAY_TYPE: |
| 1388 | break; |
| 1389 | |
| 1390 | case TK_FUNCTION_TYPE: |
| 1391 | break; |
| 1392 | |
| 1393 | case TK_ENUMERAL_TYPE: |
| 1394 | break; |
| 1395 | |
| 1396 | case TK_POINTER_TYPE: |
| 1397 | case TK_POINTER_MEMBER_TYPE: |
| 1398 | { |
| 1399 | /* Pointer type_info. Adds two fields, qualification mask and |
| 1400 | pointer to the pointed to type. This is really a |
| 1401 | descendant of __pbase_type_info. */ |
| 1402 | tree fld_mask = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1403 | NULL_TREE, integer_type_node); |
| 1404 | DECL_CHAIN (fld_mask) = fields; |
| 1405 | fields = fld_mask; |
| 1406 | |
| 1407 | tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1408 | NULL_TREE, const_ptr_type_node); |
| 1409 | DECL_CHAIN (fld_ptr) = fields; |
| 1410 | fields = fld_ptr; |
| 1411 | |
| 1412 | if (ix == TK_POINTER_MEMBER_TYPE) |
| 1413 | { |
| 1414 | /* Add a pointer to the class too. */ |
| 1415 | tree fld_cls = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1416 | NULL_TREE, const_ptr_type_node); |
| 1417 | DECL_CHAIN (fld_cls) = fields; |
| 1418 | fields = fld_cls; |
| 1419 | } |
| 1420 | break; |
| 1421 | } |
| 1422 | |
| 1423 | case TK_CLASS_TYPE: |
| 1424 | /* Class type_info. No additional fields. */ |
| 1425 | break; |
| 1426 | |
| 1427 | case TK_SI_CLASS_TYPE: |
| 1428 | { |
| 1429 | /* Single public non-virtual base class. Add pointer to base |
| 1430 | class. This is really a descendant of |
| 1431 | __class_type_info. */ |
| 1432 | tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1433 | NULL_TREE, const_ptr_type_node); |
| 1434 | DECL_CHAIN (fld_ptr) = fields; |
| 1435 | fields = fld_ptr; |
| 1436 | break; |
| 1437 | } |
| 1438 | |
| 1439 | default: /* Multiple inheritance. */ |
| 1440 | { |
| 1441 | unsigned num_bases = ix - TK_VMI_CLASS_TYPES + 1; |
| 1442 | |
| 1443 | tree fld_flg = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1444 | NULL_TREE, integer_type_node); |
| 1445 | DECL_CHAIN (fld_flg) = fields; |
| 1446 | fields = fld_flg; |
| 1447 | |
| 1448 | tree fld_cnt = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1449 | NULL_TREE, integer_type_node); |
| 1450 | DECL_CHAIN (fld_cnt) = fields; |
| 1451 | fields = fld_cnt; |
| 1452 | |
| 1453 | /* Create the array of __base_class_type_info entries. */ |
| 1454 | tree domain = build_index_type (size_int (num_bases - 1)); |
| 1455 | tree array = build_array_type (get_tinfo_desc (ix: TK_BASE_TYPE)->type, |
| 1456 | domain); |
| 1457 | tree fld_ary = build_decl (BUILTINS_LOCATION, FIELD_DECL, |
| 1458 | NULL_TREE, array); |
| 1459 | DECL_CHAIN (fld_ary) = fields; |
| 1460 | fields = fld_ary; |
| 1461 | break; |
| 1462 | } |
| 1463 | } |
| 1464 | |
| 1465 | /* Generate the pseudo type name. */ |
| 1466 | const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES |
| 1467 | ? ix : unsigned (TK_VMI_CLASS_TYPES)]; |
| 1468 | size_t name_len = strlen (s: real_name); |
| 1469 | char *pseudo_name = (char *) alloca (name_len + 30); |
| 1470 | memcpy (dest: pseudo_name, src: real_name, n: name_len); |
| 1471 | /* Those >= TK_VMI_CLASS_TYPES need a discriminator, may as well |
| 1472 | apply it to all. See get_peudo_tinfo_index where we make use of |
| 1473 | this. */ |
| 1474 | sprintf (s: pseudo_name + name_len, format: "_pseudo_%d" , ix); |
| 1475 | |
| 1476 | /* Create the pseudo type. */ |
| 1477 | tree pseudo_type = make_class_type (RECORD_TYPE); |
| 1478 | /* Pass the fields chained in reverse. */ |
| 1479 | finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); |
| 1480 | CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; |
| 1481 | DECL_CONTEXT (TYPE_NAME (pseudo_type)) = FROB_CONTEXT (global_namespace); |
| 1482 | DECL_TINFO_P (TYPE_NAME (pseudo_type)) = true; |
| 1483 | xref_basetypes (pseudo_type, /*bases=*/NULL_TREE); |
| 1484 | |
| 1485 | res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); |
| 1486 | res->name = get_identifier (real_name); |
| 1487 | |
| 1488 | /* Pretend this is public so determine_visibility doesn't give vtables |
| 1489 | internal linkage. */ |
| 1490 | TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1; |
| 1491 | |
| 1492 | return res; |
| 1493 | } |
| 1494 | |
| 1495 | /* Return an identifying index for the pseudo type_info TYPE. |
| 1496 | We wrote the index at the end of the name, so just scan it from |
| 1497 | there. This isn't critical, as it's only on the first use of this |
| 1498 | type during module stream out. */ |
| 1499 | |
| 1500 | unsigned |
| 1501 | get_pseudo_tinfo_index (tree type) |
| 1502 | { |
| 1503 | tree name = DECL_NAME (TYPE_NAME (type)); |
| 1504 | unsigned ix = 0, scale = 1; |
| 1505 | size_t len = IDENTIFIER_LENGTH (name); |
| 1506 | const char *ptr = IDENTIFIER_POINTER (name) + len; |
| 1507 | |
| 1508 | for (; *--ptr != '_'; scale *= 10) |
| 1509 | { |
| 1510 | len--; |
| 1511 | gcc_checking_assert (len && ISDIGIT (*ptr)); |
| 1512 | ix += (*ptr - '0') * scale; |
| 1513 | } |
| 1514 | |
| 1515 | gcc_assert (len != IDENTIFIER_LENGTH (name)); |
| 1516 | return ix; |
| 1517 | } |
| 1518 | |
| 1519 | tree |
| 1520 | get_pseudo_tinfo_type (unsigned ix) |
| 1521 | { |
| 1522 | return get_tinfo_desc (ix)->type; |
| 1523 | } |
| 1524 | |
| 1525 | /* We lazily create the type info types. */ |
| 1526 | |
| 1527 | static void |
| 1528 | create_tinfo_types (void) |
| 1529 | { |
| 1530 | gcc_assert (!tinfo_descs); |
| 1531 | |
| 1532 | vec_alloc (v&: tinfo_descs, nelems: TK_MAX + 20); |
| 1533 | } |
| 1534 | |
| 1535 | /* Helper for emit_support_tinfos. Emits the type_info descriptor of |
| 1536 | a single type. */ |
| 1537 | |
| 1538 | void |
| 1539 | emit_support_tinfo_1 (tree bltn) |
| 1540 | { |
| 1541 | tree types[3]; |
| 1542 | |
| 1543 | if (bltn == NULL_TREE) |
| 1544 | return; |
| 1545 | types[0] = bltn; |
| 1546 | types[1] = build_pointer_type (bltn); |
| 1547 | types[2] = build_pointer_type (cp_build_qualified_type (bltn, |
| 1548 | TYPE_QUAL_CONST)); |
| 1549 | |
| 1550 | for (int i = 0; i < 3; ++i) |
| 1551 | { |
| 1552 | tree tinfo = get_tinfo_decl (type: types[i]); |
| 1553 | TREE_USED (tinfo) = 1; |
| 1554 | mark_needed (tinfo); |
| 1555 | /* The C++ ABI requires that these objects be COMDAT. But, |
| 1556 | On systems without weak symbols, initialized COMDAT |
| 1557 | objects are emitted with internal linkage. (See |
| 1558 | comdat_linkage for details.) Since we want these objects |
| 1559 | to have external linkage so that copies do not have to be |
| 1560 | emitted in code outside the runtime library, we make them |
| 1561 | non-COMDAT here. |
| 1562 | |
| 1563 | It might also not be necessary to follow this detail of the |
| 1564 | ABI. */ |
| 1565 | if (!flag_weak || ! targetm.cxx.library_rtti_comdat ()) |
| 1566 | { |
| 1567 | gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo)); |
| 1568 | DECL_INTERFACE_KNOWN (tinfo) = 1; |
| 1569 | } |
| 1570 | |
| 1571 | /* Emit it right away if not emitted already. */ |
| 1572 | if (DECL_INITIAL (tinfo) == NULL_TREE) |
| 1573 | { |
| 1574 | bool ok = emit_tinfo_decl (tinfo); |
| 1575 | gcc_assert (ok); |
| 1576 | /* When compiling libsupc++.a (fundamental_type_info.o), |
| 1577 | unemitted_tinfo_decls->last () will be tinfo, so pop it |
| 1578 | from the vector as it is emitted now. If one uses typeid |
| 1579 | etc. in the same TU as the definition of |
| 1580 | ~fundamental_type_info (), the tinfo might be emitted |
| 1581 | already earlier, in such case keep it in the vector |
| 1582 | (as otherwise we'd need to walk the whole vector) and |
| 1583 | let c_parse_final_cleanups ignore it when it will have |
| 1584 | non-NULL DECL_INITIAL. */ |
| 1585 | if (unemitted_tinfo_decls->last () == tinfo) |
| 1586 | unemitted_tinfo_decls->pop (); |
| 1587 | } |
| 1588 | } |
| 1589 | } |
| 1590 | |
| 1591 | /* Emit the type_info descriptors which are guaranteed to be in the runtime |
| 1592 | support. Generating them here guarantees consistency with the other |
| 1593 | structures. We use the following heuristic to determine when the runtime |
| 1594 | is being generated. If std::__fundamental_type_info is defined, and its |
| 1595 | destructor is defined, then the runtime is being built. */ |
| 1596 | |
| 1597 | void |
| 1598 | emit_support_tinfos (void) |
| 1599 | { |
| 1600 | /* Dummy static variable so we can put nullptr in the array; it will be |
| 1601 | set before we actually start to walk the array. */ |
| 1602 | static tree *const fundamentals[] = |
| 1603 | { |
| 1604 | &void_type_node, |
| 1605 | &boolean_type_node, |
| 1606 | &wchar_type_node, &char8_type_node, &char16_type_node, &char32_type_node, |
| 1607 | &char_type_node, &signed_char_type_node, &unsigned_char_type_node, |
| 1608 | &short_integer_type_node, &short_unsigned_type_node, |
| 1609 | &integer_type_node, &unsigned_type_node, |
| 1610 | &long_integer_type_node, &long_unsigned_type_node, |
| 1611 | &long_long_integer_type_node, &long_long_unsigned_type_node, |
| 1612 | &float_type_node, &double_type_node, &long_double_type_node, |
| 1613 | &bfloat16_type_node, &float16_type_node, &float32_type_node, |
| 1614 | &float64_type_node, &float128_type_node, &float32x_type_node, |
| 1615 | &float64x_type_node, &float128x_type_node, &nullptr_type_node, |
| 1616 | 0 |
| 1617 | }; |
| 1618 | /* Similar, but for floating point types only which should get type info |
| 1619 | regardless whether they are non-NULL or NULL. */ |
| 1620 | static tree *const fundamentals_with_fallback[] = |
| 1621 | { |
| 1622 | &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node, |
| 1623 | 0 |
| 1624 | }; |
| 1625 | int ix; |
| 1626 | |
| 1627 | /* Look for a defined class. */ |
| 1628 | tree bltn_type = lookup_qualified_name |
| 1629 | (abi_node, name: "__fundamental_type_info" , LOOK_want::TYPE, false); |
| 1630 | if (TREE_CODE (bltn_type) != TYPE_DECL) |
| 1631 | return; |
| 1632 | |
| 1633 | bltn_type = TREE_TYPE (bltn_type); |
| 1634 | if (!COMPLETE_TYPE_P (bltn_type)) |
| 1635 | return; |
| 1636 | tree dtor = CLASSTYPE_DESTRUCTOR (bltn_type); |
| 1637 | if (!dtor || DECL_EXTERNAL (dtor)) |
| 1638 | return; |
| 1639 | |
| 1640 | /* All these are really builtins. So set the location. */ |
| 1641 | location_t saved_loc = input_location; |
| 1642 | input_location = BUILTINS_LOCATION; |
| 1643 | doing_runtime = 1; |
| 1644 | tree fallback = NULL_TREE; |
| 1645 | for (ix = 0; fundamentals[ix]; ix++) |
| 1646 | emit_support_tinfo_1 (bltn: *fundamentals[ix]); |
| 1647 | for (ix = 0; fundamentals_with_fallback[ix]; ix++) |
| 1648 | if (*fundamentals_with_fallback[ix]) |
| 1649 | emit_support_tinfo_1 (bltn: *fundamentals_with_fallback[ix]); |
| 1650 | else |
| 1651 | { |
| 1652 | if (fallback == NULL_TREE) |
| 1653 | fallback = make_node (REAL_TYPE); |
| 1654 | *fundamentals_with_fallback[ix] = fallback; |
| 1655 | emit_support_tinfo_1 (bltn: fallback); |
| 1656 | *fundamentals_with_fallback[ix] = NULL_TREE; |
| 1657 | } |
| 1658 | for (ix = 0; ix < NUM_INT_N_ENTS; ix ++) |
| 1659 | if (int_n_enabled_p[ix]) |
| 1660 | { |
| 1661 | emit_support_tinfo_1 (bltn: int_n_trees[ix].signed_type); |
| 1662 | emit_support_tinfo_1 (bltn: int_n_trees[ix].unsigned_type); |
| 1663 | } |
| 1664 | for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t)) |
| 1665 | emit_support_tinfo_1 (TREE_VALUE (t)); |
| 1666 | |
| 1667 | /* Emit additional typeinfos as requested by target. */ |
| 1668 | targetm.emit_support_tinfos (emit_support_tinfo_1); |
| 1669 | |
| 1670 | input_location = saved_loc; |
| 1671 | } |
| 1672 | |
| 1673 | /* Finish a type info decl. DECL_PTR is a pointer to an unemitted |
| 1674 | tinfo decl. Determine whether it needs emitting, and if so |
| 1675 | generate the initializer. */ |
| 1676 | |
| 1677 | bool |
| 1678 | emit_tinfo_decl (tree decl) |
| 1679 | { |
| 1680 | gcc_assert (DECL_TINFO_P (decl)); |
| 1681 | |
| 1682 | tree type = TREE_TYPE (DECL_NAME (decl)); |
| 1683 | if (typeinfo_in_lib_p (type)) |
| 1684 | { |
| 1685 | if (doing_runtime) |
| 1686 | DECL_EXTERNAL (decl) = 0; |
| 1687 | else |
| 1688 | { |
| 1689 | /* If we're not in the runtime, then DECL (which is already |
| 1690 | DECL_EXTERNAL) will not be defined here. */ |
| 1691 | DECL_INTERFACE_KNOWN (decl) = 1; |
| 1692 | return false; |
| 1693 | } |
| 1694 | } |
| 1695 | else if (involves_incomplete_p (type)) |
| 1696 | { |
| 1697 | if (!decl_needed_p (decl)) |
| 1698 | return false; |
| 1699 | /* If TYPE involves an incomplete class type, then the typeinfo |
| 1700 | object will be emitted with internal linkage. There is no |
| 1701 | way to know whether or not types are incomplete until the end |
| 1702 | of the compilation, so this determination must be deferred |
| 1703 | until this point. */ |
| 1704 | TREE_PUBLIC (decl) = 0; |
| 1705 | DECL_EXTERNAL (decl) = 0; |
| 1706 | DECL_INTERFACE_KNOWN (decl) = 1; |
| 1707 | } |
| 1708 | |
| 1709 | import_export_decl (decl); |
| 1710 | if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl)) |
| 1711 | { |
| 1712 | tree init; |
| 1713 | |
| 1714 | DECL_EXTERNAL (decl) = 0; |
| 1715 | int pseudo_ix = get_pseudo_ti_index (type); |
| 1716 | const tinfo_s *ti = get_tinfo_desc (ix: pseudo_ix); |
| 1717 | if (TREE_TYPE (decl) != ti->type) |
| 1718 | { |
| 1719 | /* If the class became complete since we first called get_tinfo_decl, |
| 1720 | its type_info descriptor may have switched from __class_type_info |
| 1721 | to e.g. __si_class_type_info. */ |
| 1722 | TREE_TYPE (decl) = ti->type; |
| 1723 | relayout_decl (decl); |
| 1724 | } |
| 1725 | init = get_pseudo_ti_init (type, tk_index: pseudo_ix); |
| 1726 | DECL_INITIAL (decl) = init; |
| 1727 | mark_used (decl); |
| 1728 | cp_finish_decl (decl, init, false, NULL_TREE, 0); |
| 1729 | /* Avoid targets optionally bumping up the alignment to improve |
| 1730 | vector instruction accesses, tinfo are never accessed this way. */ |
| 1731 | #ifdef DATA_ABI_ALIGNMENT |
| 1732 | SET_DECL_ALIGN (decl, DATA_ABI_ALIGNMENT (TREE_TYPE (decl), |
| 1733 | TYPE_ALIGN (TREE_TYPE (decl)))); |
| 1734 | DECL_USER_ALIGN (decl) = true; |
| 1735 | #endif |
| 1736 | return true; |
| 1737 | } |
| 1738 | else |
| 1739 | return false; |
| 1740 | } |
| 1741 | |
| 1742 | #include "gt-cp-rtti.h" |
| 1743 | |