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 create_pseudo_type_info (const char *real_name, int ident, ...) { tree pseudo_type; char *pseudo_name; tree fields; tree field_decl; tree result; va_list ap; va_start (ap, ident); /* Generate the pseudo type name. */ pseudo_name = alloca (strlen (real_name) + 30); strcpy (pseudo_name, real_name); strcat (pseudo_name, "_pseudo"); if (ident) sprintf (pseudo_name + strlen (pseudo_name), "%d", ident); /* First field is the pseudo type_info base class. */ fields = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node); /* Now add the derived fields. */ while ((field_decl = va_arg (ap, tree))) { TREE_CHAIN (field_decl) = fields; fields = field_decl; } /* Create the pseudo type. */ pseudo_type = make_aggr_type (RECORD_TYPE); finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); TINFO_REAL_NAME (result) = get_identifier (real_name); TINFO_PSEUDO_TYPE (result) = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); va_end (ap); return result; }