📄 sig.c
字号:
tree name = NULL_TREE; tree decl = NULL_TREE; tree init_expr; push_obstacks_nochange (); end_temporary_allocation (); if (! IS_SIGNATURE (rhs_type)) { name = get_sigtable_name (sig_type, rhs_type); decl = IDENTIFIER_GLOBAL_VALUE (name); } if (decl == NULL_TREE) { tree init = NULL_TREE; /* We allow only one signature table to be generated for signatures with opaque types. Otherwise we create a loophole in the type system since we could cast data from one classes implementation of the opaque type to that of another class. */ if (SIGNATURE_HAS_OPAQUE_TYPEDECLS (sig_type) && SIGTABLE_HAS_BEEN_GENERATED (sig_type)) { error ("signature with opaque type implemented by multiple classes"); return error_mark_node; } SIGTABLE_HAS_BEEN_GENERATED (sig_type) = 1; init_expr = build_signature_table_constructor (sig_type, init_from); if (init_expr == NULL_TREE || TREE_CODE (init_expr) != CONSTRUCTOR) return init_expr; if (name == NULL_TREE) name = get_sigtable_name (sig_type, rhs_type); { tree context = current_function_decl; /* Make the signature table global, not just static in whichever function a signature pointer/ref is used for the first time. */ current_function_decl = NULL_TREE; decl = pushdecl_top_level (build_decl (VAR_DECL, name, sig_type)); current_function_decl = context; } SET_IDENTIFIER_GLOBAL_VALUE (name, decl); store_init_value (decl, init_expr); if (IS_SIGNATURE (rhs_type)) { init = DECL_INITIAL (decl); DECL_INITIAL (decl) = error_mark_node; } DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node), DECL_ALIGN (decl));#if 0 /* GDB-4.7 doesn't find the initialization value of a signature table when it is constant. */ TREE_READONLY (decl) = 1;#endif TREE_STATIC (decl) = 1; TREE_USED (decl) = 1; make_decl_rtl (decl, NULL, 1); if (IS_SIGNATURE (rhs_type)) expand_static_init (decl, init); } pop_obstacks (); return decl;}/* Create a constructor or modify expression if the LHS of an assignment is a signature pointer or a signature reference. If LHS is a record type node, we build a constructor, otherwise a compound expression. */treebuild_signature_pointer_constructor (lhs, rhs) tree lhs, rhs;{ register struct obstack *ambient_obstack = current_obstack; register struct obstack *ambient_saveable_obstack = saveable_obstack; int initp = (TREE_CODE (lhs) == RECORD_TYPE); tree lhstype = initp ? lhs : TREE_TYPE (lhs); tree rhstype = TREE_TYPE (rhs); tree sig_ty = SIGNATURE_TYPE (lhstype); tree sig_tbl, sptr_expr, optr_expr; tree result; if (! ((TREE_CODE (rhstype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE) || (TYPE_LANG_SPECIFIC (rhstype) && (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype))))) { error ("invalid assignment to signature pointer or reference"); return error_mark_node; } if (TYPE_SIZE (sig_ty) == NULL_TREE) { cp_error ("undefined signature `%T' used in signature %s declaration", sig_ty, IS_SIGNATURE_POINTER (lhstype) ? "pointer" : "reference"); return error_mark_node; } /* If SIG_TY is permanent, make the signature table constructor and the signature pointer/reference constructor permanent too. */ if (TREE_PERMANENT (sig_ty)) { current_obstack = &permanent_obstack; saveable_obstack = &permanent_obstack; } if (TYPE_LANG_SPECIFIC (rhstype) && (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype))) { if (SIGNATURE_TYPE (rhstype) == sig_ty) { /* LHS and RHS are signature pointers/refs of the same signature. */ optr_expr = build_optr_ref (rhs); sptr_expr = build_sptr_ref (rhs); } else { /* We need to create a new signature table and copy elements from the rhs signature table. */ tree rhs_sptr_ref = build_sptr_ref (rhs); tree rhs_tbl = build1 (INDIRECT_REF, SIGNATURE_TYPE (rhstype), rhs_sptr_ref); sig_tbl = build_sigtable (sig_ty, SIGNATURE_TYPE (rhstype), rhs_tbl); if (sig_tbl == error_mark_node) return error_mark_node; optr_expr = build_optr_ref (rhs); if (sig_tbl == NULL_TREE) /* The signature was empty. The signature pointer is pretty useless, but the user has been warned. */ sptr_expr = copy_node (null_pointer_node); else if (sig_tbl == integer_zero_node) sptr_expr = rhs_sptr_ref; else sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); } } else { sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs); if (sig_tbl == error_mark_node) return error_mark_node; optr_expr = rhs; if (sig_tbl == NULL_TREE) /* The signature was empty. The signature pointer is pretty useless, but the user has been warned. */ { sptr_expr = copy_node (null_pointer_node); TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); } else sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); } if (initp) { result = tree_cons (NULL_TREE, optr_expr, build_tree_list (NULL_TREE, sptr_expr)); result = build_nt (CONSTRUCTOR, NULL_TREE, result); result = digest_init (lhstype, result, 0); } else { if (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)) readonly_error (lhs, "assignment", 0); optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR, optr_expr); sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR, sptr_expr); result = tree_cons (NULL_TREE, optr_expr, tree_cons (NULL_TREE, sptr_expr, build_tree_list (NULL_TREE, lhs))); result = build_compound_expr (result); } current_obstack = ambient_obstack; saveable_obstack = ambient_saveable_obstack; return result;}/* Build a temporary variable declaration for the instance of a signature member function call if it isn't a declaration node already. Simply using a SAVE_EXPR doesn't work since we need `this' in both branches of a conditional expression. */static treesave_this (instance) tree instance;{ tree decl; if (TREE_CODE_CLASS (TREE_CODE (instance)) == 'd') decl = instance; else { decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (instance)); DECL_REGISTER (decl) = 1; layout_decl (decl, 0); expand_decl (decl); } return decl;}/* Build a signature member function call. Looks up the signature table entry corresponding to FUNCTION. Depending on the value of the CODE field, either call the function in PFN directly, or use OFFSET to index the object's virtual function table. */treebuild_signature_method_call (function, parms) tree function, parms;{ tree instance = TREE_VALUE (parms); tree saved_instance = save_this (instance); /* Create temp for `this'. */ tree object_ptr = build_optr_ref (saved_instance); tree new_object_ptr, new_parms; tree signature_tbl_ptr = build_sptr_ref (saved_instance); tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function)); tree basetype = DECL_CONTEXT (function); tree basetype_path = TYPE_BINFO (basetype); tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype, signature_tbl_ptr), sig_field_name, basetype_path, 1); tree tag, delta, pfn, vt_off, idx, vfn; tree deflt_call = NULL_TREE, direct_call, virtual_call, result; tbl_entry = save_expr (tbl_entry); tag = build_component_ref (tbl_entry, tag_identifier, NULL_TREE, 1); delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1); pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1); vt_off = build_component_ref (tbl_entry, vt_off_identifier, NULL_TREE, 1); idx = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1); TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function)); if (IS_DEFAULT_IMPLEMENTATION (function)) { pfn = save_expr (pfn); deflt_call = build_function_call (pfn, parms); } new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype), cp_convert (ptrdiff_type_node, object_ptr), cp_convert (ptrdiff_type_node, delta)); parms = tree_cons (NULL_TREE, cp_convert (build_pointer_type (basetype), object_ptr), TREE_CHAIN (parms)); new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms)); { /* Cast the signature method to have `this' of a normal pointer type. */ tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))); TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = build_qualified_type (build_pointer_type (basetype), TYPE_QUALS (old_this)); direct_call = build_function_call (pfn, new_parms); { tree vfld, vtbl, aref; vfld = build (PLUS_EXPR, build_pointer_type (build_pointer_type (vtbl_type_node)), cp_convert (ptrdiff_type_node, object_ptr), cp_convert (ptrdiff_type_node, vt_off)); vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR), NULL_PTR); aref = build_array_ref (vtbl, idx); if (flag_vtable_thunks) vfn = aref; else vfn = build_component_ref (aref, pfn_identifier, NULL_TREE, 0); TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); virtual_call = build_function_call (vfn, new_parms); } /* Undo the cast, make `this' a signature pointer again. */ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this; } /* Once the function was found, there should be no reason why we couldn't build the member function pointer call. */ if (!direct_call || direct_call == error_mark_node || !virtual_call || virtual_call == error_mark_node || (IS_DEFAULT_IMPLEMENTATION (function) && (!deflt_call || deflt_call == error_mark_node))) { compiler_error ("cannot build call of signature member function `%s'", fndecl_as_string (function, 1)); return error_mark_node; } if (IS_DEFAULT_IMPLEMENTATION (function)) { tree test = build_binary_op_nodefault (LT_EXPR, tag, integer_zero_node, LT_EXPR); result = build_conditional_expr (tag, build_conditional_expr (test, deflt_call, virtual_call), direct_call); } else result = build_conditional_expr (tag, virtual_call, direct_call); /* If we created a temporary variable for `this', initialize it first. */ if (instance != saved_instance) result = build (COMPOUND_EXPR, TREE_TYPE (result), build_modify_expr (saved_instance, NOP_EXPR, instance), result); return result;}/* Create a COMPONENT_REF expression for referencing the OPTR field of a signature pointer or reference. */treebuild_optr_ref (instance) tree instance;{ tree field = get_identifier (SIGNATURE_OPTR_NAME); return build_component_ref (instance, field, NULL_TREE, 1);}/* Create a COMPONENT_REF expression for referencing the SPTR field of a signature pointer or reference. */static treebuild_sptr_ref (instance) tree instance;{ tree field = get_identifier (SIGNATURE_SPTR_NAME); return build_component_ref (instance, field, NULL_TREE, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -