tree get_tinfo_decl (tree type) { tree name; tree d; if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) { error ("cannot create type information for type %qT because " "its size is variable", type); return error_mark_node; } if (TREE_CODE (type) == METHOD_TYPE) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); /* For a class type, the variable is cached in the type node itself. */ if (CLASS_TYPE_P (type)) { d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)); if (d) return d; } name = mangle_typeinfo_for_type (type); d = IDENTIFIER_GLOBAL_VALUE (name); if (!d) { tree var_desc = get_pseudo_ti_desc (type); d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc)); SET_DECL_ASSEMBLER_NAME (d, name); /* Remember the type it is for. */ TREE_TYPE (name) = type; DECL_TINFO_P (d) = 1; DECL_ARTIFICIAL (d) = 1; #ifdef KEY /* g++ does not actually ignore it (note push operation below), so we cannot either */ if (!flag_spin_file) #endif DECL_IGNORED_P (d) = 1; TREE_READONLY (d) = 1; TREE_STATIC (d) = 1; /* Mark the variable as undefined -- but remember that we can define it later if we need to do so. */ DECL_EXTERNAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; if (CLASS_TYPE_P (type)) CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; set_linkage_according_to_type (type, d); pushdecl_top_level_and_finish (d, NULL_TREE); /* Add decl to the global array of tinfo decls. */ VEC_safe_push (tree, unemitted_tinfo_decls, d); }
static tree tinfo_base_init (tree desc, tree target) { tree init = NULL_TREE; tree name_decl; tree vtable_ptr; { tree name_name; /* Generate the NTBS array variable. */ tree name_type = build_cplus_array_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST), NULL_TREE); tree name_string = tinfo_name (target); /* Determine the name of the variable -- and remember with which type it is associated. */ name_name = mangle_typeinfo_string_for_type (target); TREE_TYPE (name_name) = target; name_decl = build_lang_decl (VAR_DECL, name_name, name_type); SET_DECL_ASSEMBLER_NAME (name_decl, name_name); DECL_ARTIFICIAL (name_decl) = 1; DECL_IGNORED_P (name_decl) = 1; TREE_READONLY (name_decl) = 1; TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; DECL_TINFO_P (name_decl) = 1; if (involves_incomplete_p (target)) { TREE_PUBLIC (name_decl) = 0; DECL_INTERFACE_KNOWN (name_decl) = 1; } else set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); } vtable_ptr = TINFO_VTABLE_DECL (desc); if (!vtable_ptr) { tree real_type; push_nested_namespace (abi_node); real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), /* APPLE LOCAL 4184203 */ /*tag_scope=*/ts_global, false); pop_nested_namespace (abi_node); if (!COMPLETE_TYPE_P (real_type)) { /* We never saw a definition of this type, so we need to tell the compiler that this is an exported class, as indeed all of the __*_type_info classes are. */ SET_CLASSTYPE_INTERFACE_KNOWN (real_type); CLASSTYPE_INTERFACE_ONLY (real_type) = 1; } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, size_binop (MULT_EXPR, size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), TYPE_SIZE_UNIT (vtable_entry_type))); TINFO_VTABLE_DECL (desc) = vtable_ptr; } init = tree_cons (NULL_TREE, vtable_ptr, init); init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); return init; }