📄 rtti.c
字号:
{ tree name_string; tree fn, tmp; const char *name; int i = CLASSTYPE_N_BASECLASSES (type); int base_cnt = 0; tree binfos = TYPE_BINFO_BASETYPES (type);#if 0 /* See code below that used these. */ tree vb = CLASSTYPE_VBASECLASSES (type); int n_base = i;#endif tree base, elems, access, offset, isvir; tree elt, elts = NULL_TREE; static tree base_info_type_node; if (base_info_type_node == NULL_TREE) { tree fields [4]; /* A reasonably close approximation of __class_type_info::base_info */ push_obstacks (&permanent_obstack, &permanent_obstack); base_info_type_node = make_lang_type (RECORD_TYPE); /* Actually const __user_type_info * */ fields [0] = build_lang_field_decl (FIELD_DECL, NULL_TREE, build_pointer_type (build_qualified_type (type_info_type_node, TYPE_QUAL_CONST))); fields [1] = build_lang_field_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); DECL_BIT_FIELD (fields[1]) = 1; DECL_FIELD_SIZE (fields[1]) = 29; fields [2] = build_lang_field_decl (FIELD_DECL, NULL_TREE, boolean_type_node); DECL_BIT_FIELD (fields[2]) = 1; DECL_FIELD_SIZE (fields[2]) = 1; /* Actually enum access */ fields [3] = build_lang_field_decl (FIELD_DECL, NULL_TREE, integer_type_node); DECL_BIT_FIELD (fields[3]) = 1; DECL_FIELD_SIZE (fields[3]) = 2; finish_builtin_type (base_info_type_node, "__base_info", fields, 3, ptr_type_node); pop_obstacks (); } while (--i >= 0) { tree binfo = TREE_VEC_ELT (binfos, i); expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo))); base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo))); if (TREE_VIA_VIRTUAL (binfo)) { tree t = BINFO_TYPE (binfo); const char *name; tree field; FORMAT_VBASE_NAME (name, t); field = lookup_field (type, get_identifier (name), 0, 0); offset = size_binop (FLOOR_DIV_EXPR, DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT)); offset = convert (sizetype, offset); } else offset = BINFO_OFFSET (binfo); if (TREE_VIA_PUBLIC (binfo)) access = access_public_node; else if (TREE_VIA_PROTECTED (binfo)) access = access_protected_node; else access = access_private_node; if (TREE_VIA_VIRTUAL (binfo)) isvir = boolean_true_node; else isvir = boolean_false_node; elt = build (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons (NULL_TREE, base, tree_cons (NULL_TREE, offset, tree_cons (NULL_TREE, isvir, tree_cons (NULL_TREE, access, NULL_TREE))))); TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1; elts = expr_tree_cons (NULL_TREE, elt, elts); base_cnt++; }#if 0 i = n_base; while (vb) { tree b; access = access_public_node; while (--i >= 0) { b = TREE_VEC_ELT (binfos, i); if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b)) { if (TREE_VIA_PUBLIC (b)) access = access_public_node; else if (TREE_VIA_PROTECTED (b)) access = access_protected_node; else access = access_private_node; break; } } base = build_t_desc (BINFO_TYPE (vb), 1); offset = BINFO_OFFSET (vb); isvir = build_int_2 (1, 0); base_list = expr_tree_cons (NULL_TREE, base, base_list); isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list); acc_list = expr_tree_cons (NULL_TREE, access, acc_list); off_list = expr_tree_cons (NULL_TREE, offset, off_list); base_cnt++; vb = TREE_CHAIN (vb); }#endif name = build_overload_name (type, 1, 1); name_string = combine_strings (build_string (strlen (name)+1, name)); { tree arrtype = build_array_type (base_info_type_node, NULL_TREE); elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts); TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts) = TREE_STATIC (elts) = 1; complete_array_type (arrtype, elts, 1); } elems = tree_cons (NULL_TREE, decay_conversion (tdecl), tree_cons (NULL_TREE, decay_conversion (name_string), tree_cons (NULL_TREE, decay_conversion (elts), tree_cons (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)), NULL_TREE)))); fn = get_identifier ("__rtti_class"); if (IDENTIFIER_GLOBAL_VALUE (fn)) fn = IDENTIFIER_GLOBAL_VALUE (fn); else { push_obstacks (&permanent_obstack, &permanent_obstack); tmp = tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, const_string_type_node, tree_cons (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons (NULL_TREE, sizetype, void_list_node)))); tmp = build_function_type (void_type_node, tmp); fn = build_lang_decl (FUNCTION_DECL, fn, tmp); DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; pushdecl_top_level (fn); make_function_rtl (fn); pop_obstacks (); } mark_used (fn); fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn);}/* Build an initializer for a __pointer_type_info node. */static voidexpand_ptr_desc (tdecl, type) tree tdecl; tree type;{ tree t, elems, fn; const char *name = build_overload_name (type, 1, 1); tree name_string = combine_strings (build_string (strlen (name)+1, name)); type = TREE_TYPE (type); expand_expr_stmt (get_typeid_1 (type)); t = decay_conversion (get_tinfo_var (type)); elems = tree_cons (NULL_TREE, decay_conversion (tdecl), tree_cons (NULL_TREE, decay_conversion (name_string), tree_cons (NULL_TREE, t, NULL_TREE))); fn = get_identifier ("__rtti_ptr"); if (IDENTIFIER_GLOBAL_VALUE (fn)) fn = IDENTIFIER_GLOBAL_VALUE (fn); else { tree tmp; push_obstacks (&permanent_obstack, &permanent_obstack); tmp = tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, const_string_type_node, tree_cons (NULL_TREE, build_pointer_type (type_info_type_node), void_list_node))); tmp = build_function_type (void_type_node, tmp); fn = build_lang_decl (FUNCTION_DECL, fn, tmp); DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; pushdecl_top_level (fn); make_function_rtl (fn); pop_obstacks (); } mark_used (fn); fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn);}/* Build an initializer for a __attr_type_info node. */static voidexpand_attr_desc (tdecl, type) tree tdecl; tree type;{ tree elems, t, fn; const char *name = build_overload_name (type, 1, 1); tree name_string = combine_strings (build_string (strlen (name)+1, name)); tree attrval = build_int_2 (TYPE_QUALS (type), 0); expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type))); t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type))); elems = tree_cons (NULL_TREE, decay_conversion (tdecl), tree_cons (NULL_TREE, decay_conversion (name_string), tree_cons (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE)))); fn = get_identifier ("__rtti_attr"); if (IDENTIFIER_GLOBAL_VALUE (fn)) fn = IDENTIFIER_GLOBAL_VALUE (fn); else { tree tmp; push_obstacks (&permanent_obstack, &permanent_obstack); tmp = tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, const_string_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, build_pointer_type (type_info_type_node), void_list_node)))); tmp = build_function_type (void_type_node, tmp); fn = build_lang_decl (FUNCTION_DECL, fn, tmp); DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; pushdecl_top_level (fn); make_function_rtl (fn); pop_obstacks (); } mark_used (fn); fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn);}/* Build an initializer for a type_info node that just has a name. */static voidexpand_generic_desc (tdecl, type, fnname) tree tdecl; tree type; const char *fnname;{ const char *name = build_overload_name (type, 1, 1); tree name_string = combine_strings (build_string (strlen (name)+1, name)); tree elems = tree_cons (NULL_TREE, decay_conversion (tdecl), tree_cons (NULL_TREE, decay_conversion (name_string), NULL_TREE)); tree fn = get_identifier (fnname); if (IDENTIFIER_GLOBAL_VALUE (fn)) fn = IDENTIFIER_GLOBAL_VALUE (fn); else { tree tmp; push_obstacks (&permanent_obstack, &permanent_obstack); tmp = tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, const_string_type_node, void_list_node)); tmp = build_function_type (void_type_node, tmp); fn = build_lang_decl (FUNCTION_DECL, fn, tmp); DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; pushdecl_top_level (fn); make_function_rtl (fn); pop_obstacks (); } mark_used (fn); fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn);}/* Generate the code for a type_info initialization function. Note that we take advantage of the passage 5.2.7 Type identification [expr.typeid] Whether or not the destructor is called for the type_info object at the end of the program is unspecified. and don't bother to arrange for these objects to be destroyed. It doesn't matter, anyway, since the destructors don't do anything. This must only be called from toplevel (i.e. from finish_file)! */voidsynthesize_tinfo_fn (fndecl) tree fndecl;{ tree type = TREE_TYPE (DECL_NAME (fndecl)); tree tmp, addr, tdecl; if (at_eof) { import_export_decl (fndecl); if (DECL_REALLY_EXTERN (fndecl)) return; } tdecl = get_tinfo_var (type); DECL_EXTERNAL (tdecl) = 0; TREE_STATIC (tdecl) = 1; DECL_COMMON (tdecl) = 1; TREE_USED (tdecl) = 1; DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node); cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); start_function (NULL_TREE, fndecl, NULL_TREE, 1); store_parm_decls (); clear_last_expr (); push_momentary (); /* If the first word of the array (the vtable) is non-zero, we've already initialized the object, so don't do it again. */ addr = decay_conversion (tdecl); tmp = cp_convert (build_pointer_type (ptr_type_node), addr); tmp = build_indirect_ref (tmp, 0); tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node); expand_start_cond (tmp, 0); if (TREE_CODE (type) == FUNCTION_TYPE) expand_generic_desc (tdecl, type, "__rtti_func"); else if (TREE_CODE (type) == ARRAY_TYPE) expand_generic_desc (tdecl, type, "__rtti_array"); else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED) expand_attr_desc (tdecl, type); else if (TREE_CODE (type) == POINTER_TYPE) { if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) expand_generic_desc (tdecl, type, "__rtti_ptmd"); else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE) expand_generic_desc (tdecl, type, "__rtti_ptmf"); else expand_ptr_desc (tdecl, type); } else if (TYPE_PTRMEMFUNC_P (type)) expand_generic_desc (tdecl, type, "__rtti_ptmf"); else if (IS_AGGR_TYPE (type)) { if (CLASSTYPE_N_BASECLASSES (type) == 0) expand_generic_desc (tdecl, type, "__rtti_user"); else if (! TYPE_USES_COMPLEX_INHERITANCE (type) && (TREE_VIA_PUBLIC (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) expand_si_desc (tdecl, type); else expand_class_desc (tdecl, type); } else if (TREE_CODE (type) == ENUMERAL_TYPE) expand_generic_desc (tdecl, type, "__rtti_user"); else my_friendly_abort (252); expand_end_cond (); /* OK, now return the type_info object. */ tmp = cp_convert (build_pointer_type (type_info_type_node), addr); tmp = build_indirect_ref (tmp, 0); c_expand_return (tmp); finish_function (lineno, 0, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -