📄 gc.c
字号:
type = TREE_TYPE (type); if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE) return exp; vptr = fold (size_binop (PLUS_EXPR, size_binop (FLOOR_DIV_EXPR, DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (type)), size_int (BITS_PER_UNIT)), exp)); vptr = build1 (INDIRECT_REF, build_pointer_type (vtable_entry_type), vptr); if (flag_vtable_thunks) offset = build_array_ref (vptr, integer_zero_node); else offset = build_component_ref (build_array_ref (vptr, integer_zero_node), delta_identifier, NULL_TREE, 0); type = build_type_variant (ptr_type_node, TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); return build (PLUS_EXPR, type, exp, convert (ptrdiff_type_node, offset));}/* Return the type_info node associated with the expression EXP. If EXP is a reference to a polymorphic class, return the dynamic type; otherwise return the static type of the expression. */treebuild_typeid (exp) tree exp;{ tree type; if (!flag_rtti) cp_error ("cannot take typeid of object when -frtti is not specified"); if (exp == error_mark_node) return error_mark_node; type = TREE_TYPE (exp); /* Strip top-level cv-qualifiers. */ type = TYPE_MAIN_VARIANT (type); /* if b is an instance of B, typeid(b) == typeid(B). Do this before reference trickiness. */ if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE) return get_typeid (type); /* peel back references, so they match. */ if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); /* Peel off cv qualifiers. */ type = TYPE_MAIN_VARIANT (type); /* Apply trivial conversion T -> T& for dereferenced ptrs. */ if (TREE_CODE (type) == RECORD_TYPE) type = build_reference_type (type); /* If exp is a reference to polymorphic type, get the real type_info. */ if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type))) { /* build reference to type_info from vtable. */ tree t; if (flag_vtable_thunks) t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_one_node); else t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_zero_node); TREE_TYPE (t) = build_pointer_type (__class_desc_type_node); t = build_indirect_ref (t, NULL); return t; } /* otherwise return the type_info for the static type of the expr. */ return get_typeid (type);}/* Return the type_info object for TYPE, creating it if necessary. */treeget_typeid (type) tree type;{ tree t, td; if (type == error_mark_node) return error_mark_node; /* Is it useful (and/or correct) to have different typeids for `T &' and `T'? */ if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); td = build_t_desc (type, 1); if (td == error_mark_node) return error_mark_node; t = TREE_OPERAND (td, 0); return t;}/* Get a bad_cast node for the program to throw... See libstdc++::exception{,.cc} for __bad_cast_object */treeget_bad_cast_node (){ static tree t; if (t == NULL_TREE && (t = lookup_name (get_identifier ("__bad_cast_object"), 0)) == NULL_TREE) { error ("you must #include <typeinfo>"); return error_mark_node; } return t;}/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working paper. */treebuild_dynamic_cast (type, expr) tree type, expr;{ enum tree_code tc = TREE_CODE (type); tree exprtype = TREE_TYPE (expr); enum tree_code ec = TREE_CODE (exprtype); tree retval; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; switch (tc) { case POINTER_TYPE: if (ec == REFERENCE_TYPE) { expr = convert_from_reference (expr); exprtype = TREE_TYPE (expr); ec = TREE_CODE (exprtype); } if (ec != POINTER_TYPE) goto fail; if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) goto fail; if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0) goto fail; if (TREE_READONLY (TREE_TYPE (exprtype)) && ! TYPE_READONLY (TREE_TYPE (type))) goto fail; if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) break; /* else fall through */ case REFERENCE_TYPE: if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE) break; /* else fall through */ default: goto fail; } /* Apply trivial conversion T -> T& for dereferenced ptrs. */ if (ec == RECORD_TYPE) { exprtype = build_type_variant (exprtype, TREE_READONLY (expr), TREE_THIS_VOLATILE (expr)); exprtype = build_reference_type (exprtype); expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, LOOKUP_NORMAL, NULL_TREE); ec = REFERENCE_TYPE; } if (tc == REFERENCE_TYPE) { if (ec != REFERENCE_TYPE) goto fail; if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) goto fail; if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0) goto fail; } /* If *type is an unambiguous accessible base class of *exprtype, convert statically. */ { int distance; tree path; distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1, &path); if (distance >= 0) return build_vbase_path (PLUS_EXPR, type, expr, path, 0); } /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype))) { /* if TYPE is `void *', return pointer to complete object. */ if (tc == POINTER_TYPE && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) { /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ if (TREE_CODE (expr) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) return build1 (NOP_EXPR, type, expr); return build_headof (expr); } else { tree retval; tree result, td1, td2, elems, tmp1, expr1; /* If we got here, we can't convert statically. Therefore, dynamic_cast<D&>(b) (b an object) cannot succeed. */ if (ec == REFERENCE_TYPE) { if (TREE_CODE (expr) == VAR_DECL && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE) { cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", expr, type); return build_throw (get_bad_cast_node ()); } } /* Ditto for dynamic_cast<D*>(&b). */ else if (TREE_CODE (expr) == ADDR_EXPR) { tree op = TREE_OPERAND (expr, 0); if (TREE_CODE (op) == VAR_DECL && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) { cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", expr, type); retval = build_int_2 (0, 0); TREE_TYPE (retval) = type; return retval; } } expr1 = expr; if (tc == REFERENCE_TYPE) expr1 = build_unary_op (ADDR_EXPR, expr1, 0); /* Build run-time conversion. */ expr1 = build_headof (expr1); if (ec == POINTER_TYPE) td1 = build_typeid (build_indirect_ref (expr, NULL_PTR)); else td1 = build_typeid (expr); if (tc == POINTER_TYPE) td2 = get_typeid (TREE_TYPE (type)); else td2 = get_typeid (type); elems = tree_cons (NULL_TREE, td2, tree_cons (NULL_TREE, build_int_2 (1, 0), tree_cons (NULL_TREE, expr1, NULL_TREE))); result = build_method_call (td1, get_identifier ("__rtti_match"), elems, NULL_TREE, LOOKUP_NORMAL); if (tc == REFERENCE_TYPE) { expr1 = build_throw (get_bad_cast_node ()); expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1, build_tree_list (NULL_TREE, convert (type, integer_zero_node)))); TREE_TYPE (expr1) = type; return build (COND_EXPR, type, result, result, expr1); } /* Now back to the type we want from a void*. */ result = convert (type, result); return result; } } fail: cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'", expr, exprtype, type); return error_mark_node;}/* Build and initialize various sorts of descriptors. Every descriptor node has a name associated with it (the name created by mangling). For this reason, we use the identifier as our access to the __*_desc nodes, instead of sticking them directly in the types. Otherwise we would burden all built-in types (and pointer types) with slots that we don't necessarily want to use. For each descriptor we build, we build a variable that contains the descriptor's information. When we need this info at runtime, all we need is access to these variables. Note: these constructors always return the address of the descriptor info, since that is simplest for their mutual interaction. */static treebuild_generic_desc (tdecl, type, elems) tree tdecl; tree type; tree elems;{ tree init = elems; int toplev = global_bindings_p (); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; TREE_READONLY (init) = 1; TREE_TYPE (tdecl) = type; DECL_INITIAL (tdecl) = init; TREE_STATIC (tdecl) = 1; DECL_SIZE (tdecl) = NULL_TREE; layout_decl (tdecl, 0); if (! toplev) push_to_top_level (); cp_finish_decl (tdecl, init, NULL_TREE, 0, 0); if (! toplev) pop_from_top_level (); if (! TREE_USED (tdecl)) { assemble_external (tdecl); TREE_USED (tdecl) = 1; } return IDENTIFIER_AS_DESC (DECL_NAME (tdecl));}/* Build an initializer for a __bltn_desc node. */static treebuild_bltn_desc (tdecl, type) tree tdecl; tree type;{ tree elems, t; if (type == boolean_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_BOOL"), 0, 0); else if (type == char_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_CHAR"), 0, 0); else if (type == short_integer_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SHORT"), 0, 0); else if (type == integer_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_INT"), 0, 0); else if (type == long_integer_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONG"), 0, 0); else if (type == long_long_integer_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONGLONG"), 0, 0); else if (type == float_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_FLOAT"), 0, 0); else if (type == double_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_DOUBLE"), 0, 0); else if (type == long_double_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LDOUBLE"), 0, 0); else if (type == unsigned_char_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UCHAR"), 0, 0); else if (type == short_unsigned_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_USHORT"), 0, 0); else if (type == unsigned_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UINT"), 0, 0); else if (type == long_unsigned_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONG"), 0, 0); else if (type == long_long_unsigned_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONGLONG"), 0, 0); else if (type == signed_char_type_node) t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SCHAR"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -