📄 sig.c
字号:
{ tree x; tree mfptr; tree last_mfptr = NULL_TREE; tree mfptr_list = NULL_TREE; for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) { if (TREE_CODE (x) == FUNCTION_DECL) { mfptr = build_member_function_pointer (x); DECL_MEMFUNC_POINTER_TO (x) = mfptr; DECL_MEMFUNC_POINTING_TO (mfptr) = x; DECL_IGNORED_P (x) = 1; DECL_IN_AGGR_P (mfptr) = 1; if (! mfptr_list) mfptr_list = last_mfptr = mfptr; else { TREE_CHAIN (last_mfptr) = mfptr; last_mfptr = mfptr; } } } /* The member function pointers must come after the TYPE_DECLs, in this case, because build_signature_table_constructor depends on finding opaque TYPE_DECLS before the functions that make use of them. */ if (last_mfptr) TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), mfptr_list);}/* Compare the types of a signature member function and a class member function. Returns 1 if the types are in the C++ `<=' relationship. If we have a signature pointer/reference as argument or return type we don't want to do a recursive conformance check. The conformance check only succeeds if both LHS and RHS refer to the same signature pointer. Otherwise we need to keep information about parameter types around at run time to initialize the signature table correctly. */static intmatch_method_types (sig_mtype, class_mtype) tree sig_mtype, class_mtype;{ tree sig_return_type = TREE_TYPE (sig_mtype); tree sig_arg_types = TYPE_ARG_TYPES (sig_mtype); tree class_return_type = TREE_TYPE (class_mtype); tree class_arg_types = TYPE_ARG_TYPES (class_mtype); /* The return types have to be the same. */ if (!same_type_p (sig_return_type, class_return_type)) return 0; /* Compare the first argument `this.' */ { /* Get the type of what the `optr' is pointing to. */ tree sig_this = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types)))); tree class_this = TREE_VALUE (class_arg_types); if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */ class_this = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (class_this))); else class_this = TREE_TYPE (class_this); /* If a signature method's `this' is const or volatile, so has to be the corresponding class method's `this.' */ if (!at_least_as_qualified_p (class_this, sig_this)) return 0; } sig_arg_types = TREE_CHAIN (sig_arg_types); class_arg_types = TREE_CHAIN (class_arg_types); /* The number of arguments and the argument types have to be the same. */ return compparms (sig_arg_types, class_arg_types);}/* Undo casts of opaque type variables to the RHS types. */static voidundo_casts (sig_ty) tree sig_ty;{ tree field = TYPE_FIELDS (sig_ty); /* Since all the FIELD_DECLs for the signature table entries are at the end of the chain (see `append_signature_fields'), we can do it this way. */ for (; field && TREE_CODE (field) != FIELD_DECL; field = TREE_CHAIN (field)) if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == opaque_type_node) TREE_TYPE (TREE_TYPE (field)) = TREE_TYPE (ptr_type_node);}/* Do the type checking necessary to see whether the `rhs' conforms to the lhs's `sig_ty'. Depending on the type of `rhs' return a NULL_TREE, an integer_zero_node, a constructor, or an expression offsetting the `rhs' signature table. */static treebuild_signature_table_constructor (sig_ty, rhs) tree sig_ty, rhs;{ tree rhstype = TREE_TYPE (rhs); tree sig_field = TYPE_FIELDS (sig_ty); tree result = NULL_TREE; tree first_rhs_field = NULL_TREE; tree last_rhs_field = NULL_TREE; int sig_ptr_p = IS_SIGNATURE (rhstype); int offset_p = sig_ptr_p; rhstype = sig_ptr_p ? rhstype : TREE_TYPE (rhstype); if (CLASSTYPE_TAGS (sig_ty)) { sorry ("conformance check with signature containing class declarations"); return error_mark_node; } for (; sig_field; sig_field = TREE_CHAIN (sig_field)) { tree basetype_path, baselink, basetypes; tree sig_method, sig_mname, sig_mtype; tree rhs_method, tbl_entry; if (TREE_CODE (sig_field) == TYPE_DECL) { tree sig_field_type = TREE_TYPE (sig_field); if (TYPE_MAIN_VARIANT (sig_field_type) == opaque_type_node) { /* We've got an opaque type here. */ tree oty_name = DECL_NAME (sig_field); tree oty_type = lookup_field (rhstype, oty_name, 1, 1); if (oty_type == NULL_TREE || oty_type == error_mark_node) { cp_error ("class `%T' does not contain type `%T'", rhstype, oty_type); undo_casts (sig_ty); return error_mark_node; } oty_type = TREE_TYPE (oty_type); /* Cast `sig_field' to be of type `oty_type'. This will be undone in `undo_casts' by walking over all the TYPE_DECLs. */ TREE_TYPE (sig_field_type) = TREE_TYPE (oty_type); } /* If we don't have an opaque type, we can ignore the `typedef'. */ continue; } /* Find the signature method corresponding to `sig_field'. */ sig_method = DECL_MEMFUNC_POINTING_TO (sig_field); sig_mname = DECL_NAME (sig_method); sig_mtype = TREE_TYPE (sig_method); basetype_path = TYPE_BINFO (rhstype); baselink = lookup_fnfields (basetype_path, sig_mname, 0); if (baselink == NULL_TREE || baselink == error_mark_node) { if (! IS_DEFAULT_IMPLEMENTATION (sig_method)) { cp_error ("class `%T' does not contain method `%D'", rhstype, sig_mname); undo_casts (sig_ty); return error_mark_node; } else { /* We use the signature's default implementation. */ rhs_method = sig_method; } } else { /* Find the class method of the correct type. */ tree rhs_methods; basetypes = TREE_PURPOSE (baselink); if (TREE_CODE (basetypes) == TREE_LIST) basetypes = TREE_VALUE (basetypes); rhs_methods = TREE_VALUE (baselink); for (; rhs_methods; rhs_methods = OVL_NEXT (rhs_methods)) if ((rhs_method = OVL_CURRENT (rhs_methods)) && sig_mname == DECL_NAME (rhs_method) && ! DECL_STATIC_FUNCTION_P (rhs_method) && match_method_types (sig_mtype, TREE_TYPE (rhs_method))) break; if (rhs_methods == NULL_TREE || !accessible_p (basetypes, rhs_method)) { cp_error ("`%T' does not contain a method conforming to `%#D'", rhstype, sig_method); undo_casts (sig_ty); return error_mark_node; } } if (sig_ptr_p && rhs_method != sig_method) { tree rhs_field = DECL_MEMFUNC_POINTER_TO (rhs_method); if (first_rhs_field == NULL_TREE) { first_rhs_field = rhs_field; last_rhs_field = rhs_field; } else if (TREE_CHAIN (last_rhs_field) == rhs_field) last_rhs_field = rhs_field; else offset_p = 0; tbl_entry = build_component_ref (rhs, DECL_NAME (rhs_field), NULL_TREE, 1); } else { tree tag, vb_off, delta, idx, pfn = NULL_TREE, vt_off = NULL_TREE; tree tag_decl, vb_off_decl, delta_decl, index_decl; tree pfn_decl, vt_off_decl; if (rhs_method == sig_method) { /* default implementation */ tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0); vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); delta = integer_zero_node; idx = integer_zero_node; pfn = build_addr_func (rhs_method); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1; TREE_TYPE (pfn) = ptr_type_node; TREE_ADDRESSABLE (rhs_method) = 1; offset_p = 0; /* we can't offset the rhs sig table */ } else if (DECL_VINDEX (rhs_method)) { /* virtual member function */ tag = integer_one_node; vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); if (flag_vtable_thunks) delta = BINFO_OFFSET (get_binfo (DECL_CONTEXT (rhs_method), rhstype, 1)); else delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1)); idx = DECL_VINDEX (rhs_method); vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method), rhstype, 0)); } else { /* non-virtual member function */ tag = integer_zero_node; vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1)); idx = integer_zero_node; pfn = build_addr_func (rhs_method); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1; TREE_TYPE (pfn) = ptr_type_node; TREE_ADDRESSABLE (rhs_method) = 1; } /* Since digest_init doesn't handle initializing selected fields of a struct (i.e., anonymous union), we build the constructor by hand, without calling digest_init. */ tag_decl = TYPE_FIELDS (sigtable_entry_type); vb_off_decl = TREE_CHAIN (tag_decl); delta_decl = TREE_CHAIN (vb_off_decl); index_decl = TREE_CHAIN (delta_decl); pfn_decl = TREE_CHAIN (index_decl); vt_off_decl = TREE_CHAIN (pfn_decl); tag = cp_convert (TREE_TYPE (tag_decl), tag); vb_off = cp_convert (TREE_TYPE (vb_off_decl), vb_off); delta = cp_convert (TREE_TYPE (delta_decl), delta); idx = cp_convert (TREE_TYPE (index_decl), idx); if (DECL_VINDEX (rhs_method)) { vt_off = cp_convert (TREE_TYPE (vt_off_decl), vt_off); tbl_entry = build_tree_list (vt_off_decl, vt_off); } else { pfn = cp_convert (TREE_TYPE (pfn_decl), pfn); tbl_entry = build_tree_list (pfn_decl, pfn); } tbl_entry = tree_cons (delta_decl, delta, tree_cons (index_decl, idx, tbl_entry)); tbl_entry = tree_cons (tag_decl, tag, tree_cons (vb_off_decl, vb_off, tbl_entry)); tbl_entry = build (CONSTRUCTOR, sigtable_entry_type, NULL_TREE, tbl_entry); TREE_CONSTANT (tbl_entry) = 1; } /* Chain those function address expressions together. */ if (result) result = tree_cons (NULL_TREE, tbl_entry, result); else result = build_tree_list (NULL_TREE, tbl_entry); } if (result == NULL_TREE) { /* The signature was empty, we don't need a signature table. */ undo_casts (sig_ty); return NULL_TREE; } if (offset_p) { if (first_rhs_field == TYPE_FIELDS (rhstype)) { /* The sptr field on the lhs can be copied from the rhs. */ undo_casts (sig_ty); return integer_zero_node; } else { /* The sptr field on the lhs will point into the rhs sigtable. */ undo_casts (sig_ty); return build_component_ref (rhs, DECL_NAME (first_rhs_field), NULL_TREE, 0); } } /* We need to construct a new signature table. */ result = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (result)); TREE_HAS_CONSTRUCTOR (result) = 1; TREE_CONSTANT (result) = !sig_ptr_p; undo_casts (sig_ty); return result;}/* Build a signature table declaration and initialize it or return an existing one if we built one already. If we don't get a constructor as initialization expression, we don't need a new signature table variable and just hand back the init expression. The declaration processing is done by hand instead of using `cp_finish_decl' so that we can make signature pointers global variables instead of static ones. */static treebuild_sigtable (sig_type, rhs_type, init_from) tree sig_type, rhs_type, init_from;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -