📄 method.c
字号:
} else { error ("ambiguous request for method pointer `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; }#endif } } if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name)) { return IDENTIFIER_LABEL_VALUE (name); } return error_mark_node; } type = TREE_TYPE (value); if (TREE_CODE (value) == FIELD_DECL) { if (current_class_ptr == NULL_TREE) { if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) cp_error ("invalid use of member `%D' in static member function", value); else /* We can get here when processing a bad default argument, like: struct S { int a; void f(int i = a); } */ cp_error ("invalid use of member `%D'", value); return error_mark_node; } TREE_USED (current_class_ptr) = 1; /* Mark so that if we are in a constructor, and then find that this field was initialized by a base initializer, we can emit an error message. */ TREE_USED (value) = 1; value = build_component_ref (current_class_ref, name, NULL_TREE, 1); } else if ((TREE_CODE (value) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (value)) || (TREE_CODE (value) == OVERLOAD && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (value)))) { tree decl; if (TREE_CODE (value) == OVERLOAD) value = OVL_CURRENT (value); if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value))) return value; decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0); value = build_component_ref (decl, name, NULL_TREE, 1); } else if (really_overloaded_fn (value)) ; else if (TREE_CODE (value) == OVERLOAD) /* not really overloaded function */ mark_used (OVL_FUNCTION (value)); else if (TREE_CODE (value) == TREE_LIST) { /* Ambiguous reference to base members, possibly other cases?. */ tree t = value; while (t && TREE_CODE (t) == TREE_LIST) { mark_used (TREE_VALUE (t)); t = TREE_CHAIN (t); } } else if (TREE_CODE (value) == NAMESPACE_DECL) { cp_error ("use of namespace `%D' as expression", value); return error_mark_node; } else if (DECL_CLASS_TEMPLATE_P (value)) { cp_error ("use of class template `%T' as expression", value); return error_mark_node; } else mark_used (value); if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL || TREE_CODE (value) == RESULT_DECL) { tree context = decl_function_context (value); if (context != NULL_TREE && context != current_function_decl && ! TREE_STATIC (value)) { cp_error ("use of %s from containing function", (TREE_CODE (value) == VAR_DECL ? "`auto' variable" : "parameter")); cp_error_at (" `%#D' declared here", value); value = error_mark_node; } } if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) { if (DECL_LANG_SPECIFIC (value) && DECL_CLASS_CONTEXT (value) != current_class_type) { tree path; register tree context = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) ? DECL_CLASS_CONTEXT (value) : DECL_CONTEXT (value); get_base_distance (context, current_class_type, 0, &path); if (path && !enforce_access (current_class_type, value)) return error_mark_node; } } else if (TREE_CODE (value) == TREE_LIST && TREE_TYPE (value) == error_mark_node) { error ("request for member `%s' is ambiguous in multiple inheritance lattice", IDENTIFIER_POINTER (name)); print_candidates (value); return error_mark_node; } if (! processing_template_decl) value = convert_from_reference (value); return value;}treemake_thunk (function, delta) tree function; int delta;{ tree thunk_id; tree thunk; tree func_decl; if (TREE_CODE (function) != ADDR_EXPR) abort (); func_decl = TREE_OPERAND (function, 0); if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); OB_INIT (); OB_PUTS ("__thunk_"); if (delta > 0) { OB_PUTC ('n'); icat (delta); } else icat (-delta); OB_PUTC ('_'); OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); OB_FINISH (); thunk_id = get_identifier (obstack_base (&scratch_obstack)); thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && TREE_CODE (thunk) != THUNK_DECL) { cp_error ("implementation-reserved name `%D' used", thunk_id); thunk = NULL_TREE; SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); } if (thunk == NULL_TREE) { thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); TREE_READONLY (thunk) = TREE_READONLY (func_decl); TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); comdat_linkage (thunk); TREE_SET_CODE (thunk, THUNK_DECL); DECL_INITIAL (thunk) = function; THUNK_DELTA (thunk) = delta; DECL_EXTERNAL (thunk) = 1; DECL_ARTIFICIAL (thunk) = 1; /* So that finish_file can write out any thunks that need to be: */ pushdecl_top_level (thunk); } return thunk;}/* Emit the definition of a C++ multiple inheritance vtable thunk. */voidemit_thunk (thunk_fndecl) tree thunk_fndecl;{ tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); int delta = THUNK_DELTA (thunk_fndecl); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; TREE_ASM_WRITTEN (thunk_fndecl) = 1; TREE_ADDRESSABLE (function) = 1; mark_used (function); if (current_function_decl) abort (); TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL); {#ifdef ASM_OUTPUT_MI_THUNK char *fnname; current_function_decl = thunk_fndecl; /* Make sure we build up its RTL before we go onto the temporary obstack. */ make_function_rtl (thunk_fndecl); temporary_allocation (); DECL_RESULT (thunk_fndecl) = build_decl (RESULT_DECL, 0, integer_type_node); fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); init_function_start (thunk_fndecl, input_filename, lineno); current_function_is_thunk = 1; assemble_start_function (thunk_fndecl, fnname); ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); assemble_end_function (thunk_fndecl, fnname); permanent_allocation (1); current_function_decl = 0;#else /* ASM_OUTPUT_MI_THUNK */ /* If we don't have the necessary macro for efficient thunks, generate a thunk function that just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ tree a, t; if (varargs_function_p (function)) cp_error ("generic thunk code fails for method `%#D' which uses `...'", function); /* Set up clone argument trees for the thunk. */ t = NULL_TREE; for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) { tree x = copy_node (a); TREE_CHAIN (x) = t; DECL_CONTEXT (x) = thunk_fndecl; t = x; } a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; DECL_RESULT (thunk_fndecl) = NULL_TREE; DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function); copy_lang_decl (thunk_fndecl); DECL_INTERFACE_KNOWN (thunk_fndecl) = 1; DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1; start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1); store_parm_decls (); current_function_is_thunk = 1; /* Build up the call to the real function. */ t = build_int_2 (delta, -1 * (delta < 0)); TREE_TYPE (t) = signed_type (sizetype); t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t)); t = expr_tree_cons (NULL_TREE, t, NULL_TREE); for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) t = expr_tree_cons (NULL_TREE, a, t); t = nreverse (t); t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); c_expand_return (t); finish_function (lineno, 0, 0); /* Don't let the backend defer this function. */ if (DECL_DEFER_OUTPUT (thunk_fndecl)) { output_inline_function (thunk_fndecl); permanent_allocation (1); }#endif /* ASM_OUTPUT_MI_THUNK */ } TREE_SET_CODE (thunk_fndecl, THUNK_DECL);}voidmaybe_vlist_ctor_wrapper (fn, definep) tree fn; int definep;{ tree fntype, decl; tree arg_types, parms, parm, basetype, pbasetype; tree t, ctors; if (!flag_vtable_thunks_compat || !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) return; arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); pbasetype = TREE_VALUE (arg_types); basetype = TREE_TYPE (pbasetype); parms = DECL_ARGUMENTS (fn); /* Skip this, __in_chrg, and _vlist */ arg_types = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_types))); /* Add __in_charge. */ arg_types = hash_tree_chain (integer_type_node, arg_types); /* Don't add this to arg_types, as build_cplus_method_type does so. */ fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), arg_types); decl = build_lang_decl (FUNCTION_DECL, DECL_NAME (fn), fntype); DECL_LANG_SPECIFIC (decl)->decl_flags = DECL_LANG_SPECIFIC (fn)->decl_flags; DECL_EXTERNAL (decl) = 0; TREE_PUBLIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_CONSTRUCTOR_P (decl) = 1; DECL_CONSTRUCTOR_FOR_VBASE (decl) = CONSTRUCTOR_FOR_VBASE; /* Claim that this is never a template instantiation. */ DECL_USE_TEMPLATE (decl) = 0; DECL_TEMPLATE_INFO (decl) = NULL_TREE; /* Set up clone argument trees for the thunk. */ parms = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms))); /* Add this */ t = build_decl (PARM_DECL, this_identifier, pbasetype); SET_DECL_ARTIFICIAL (t); DECL_ARG_TYPE (t) = pbasetype; DECL_REGISTER (t) = 1; /* Add __in_charge. */ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); SET_DECL_ARTIFICIAL (parm); DECL_ARG_TYPE (parm) = integer_type_node; TREE_CHAIN (parm) = t; t = parm; while (parms) { tree x = copy_node (parms); TREE_CHAIN (x) = t; DECL_CONTEXT (x) = decl; t = x; parms = TREE_CHAIN (parms); } parms = nreverse (t); DECL_ARGUMENTS (decl) = parms; DECL_ASSEMBLER_NAME (decl) = build_decl_overload (DECL_NAME (decl), TYPE_ARG_TYPES (TREE_TYPE (decl)), 2); ctors = CLASSTYPE_METHOD_VEC (basetype); if (ctors) ctors = TREE_VEC_ELT (ctors, 0); for ( ; ctors; ctors = OVL_NEXT (ctors)) if (DECL_ASSEMBLER_NAME (OVL_CURRENT (ctors)) == DECL_ASSEMBLER_NAME (decl)) break; if (!ctors) { add_method (basetype, 0, decl); cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0); } else decl = OVL_CURRENT (ctors); /* Remember the original function. */ DECL_VLIST_CTOR_WRAPPED (decl) = fn; /* If this is called from start_method, definep is -1. Then we are inside the class, and fn is inline by default. */ if (definep) { /* Record that the ctor is being defined, so we also emit the wrapper later. */ if (DECL_THIS_INLINE (fn) || (definep == -1)) { DECL_THIS_INLINE (decl) = 1; DECL_INLINE (decl) = 1; pushdecl_top_level (decl); } else { TREE_USED (decl) = 1; TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1; } mark_inline_for_output (decl); }}static voidemit_vlist_ctor_wrapper (decl) tree decl;{ tree t, parms, fn; current_function_is_thunk = 1; parms = DECL_ARGUMENTS (decl); fn = DECL_VLIST_CTOR_WRAPPED (decl); mark_used (fn); /* Build up the call to the real function. */ t = NULL_TREE; /* Push this, __in_charge. */ t = expr_tree_cons (NULL_TREE, parms, t); parms = TREE_CHAIN (parms); t = expr_tree_cons (NULL_TREE, parms, t); parms = TREE_CHAIN (parms); /* Push 0 as __vlist. */ t = expr_tree_cons (NULL_TREE, vlist_zero_node, t); /* Push rest of arguments. */ while (parms) { t = expr_tree_cons (NULL_TREE, parms, t); parms = TREE_CHAIN (parms); } t = nreverse (t); t = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), t); expand_expr_stmt (t);}/* Code for synthesizing methods which have default semantics defined. *//* For the anonymous union in TYPE, return the member that is at least as large as the rest of the members, so we can copy it. */static treelargest_union_member (type) tree type;{ tree f, type_size = TYPE_SIZE (type); for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) if (simple_cst_equal (DECL_SIZE (f), type_size) == 1) return f; /* We should always find one. */ my_friendly_abort (323); return NULL_TREE;}/* Generate code for default X(X&) constructor. */static voiddo_build_copy_constructor (fndecl) tree fndecl;{ tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree t; clear_last_expr (); push_momentary (); if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) parm = TREE_CHAIN (parm); if (TYPE_USES_PVBASES (current_class_type)) parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) && is_empty_class (current_class_type)) /* Don't copy the padding byte; it might not have been allocated if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { t = build (INIT_EXPR, void_type_node, current_class_ref, parm); TREE_SIDE_EFFECTS (t) = 1; cplus_expand_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); tree binfos = TYPE_BINFO_BASETYPES (current_class_type); int i; /* Initialize all the base-classes. */ for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; t = TREE_CHAIN (t)) current_base_init_list = tree_cons (BINFO_TYPE (t), parm, current_base_init_list); for (i = 0; i < n_bases; ++i) { t = TREE_VEC_ELT (binfos, i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -