tree make_alias_for (tree function, tree newid) { tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (function); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_THIS_STATIC (alias) = 1; DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; DECL_PENDING_INLINE_P (alias) = 0; DECL_INLINE (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_DEFERRED_FN (alias) = 0; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INSTANTIATED (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; return alias; }
tree get_tinfo_decl (tree type) { tree name; tree d; if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) { error ("cannot create type information for type %qT because " "its size is variable", type); return error_mark_node; } if (TREE_CODE (type) == METHOD_TYPE) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); /* For a class type, the variable is cached in the type node itself. */ if (CLASS_TYPE_P (type)) { d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)); if (d) return d; } name = mangle_typeinfo_for_type (type); d = IDENTIFIER_GLOBAL_VALUE (name); if (!d) { tree var_desc = get_pseudo_ti_desc (type); d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc)); SET_DECL_ASSEMBLER_NAME (d, name); /* Remember the type it is for. */ TREE_TYPE (name) = type; DECL_TINFO_P (d) = 1; DECL_ARTIFICIAL (d) = 1; #ifdef KEY /* g++ does not actually ignore it (note push operation below), so we cannot either */ if (!flag_spin_file) #endif DECL_IGNORED_P (d) = 1; TREE_READONLY (d) = 1; TREE_STATIC (d) = 1; /* Mark the variable as undefined -- but remember that we can define it later if we need to do so. */ DECL_EXTERNAL (d) = 1; DECL_NOT_REALLY_EXTERN (d) = 1; if (CLASS_TYPE_P (type)) CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d; set_linkage_according_to_type (type, d); pushdecl_top_level_and_finish (d, NULL_TREE); /* Add decl to the global array of tinfo decls. */ VEC_safe_push (tree, unemitted_tinfo_decls, d); }
bool emit_tinfo_decl (tree decl) { tree type = TREE_TYPE (DECL_NAME (decl)); int in_library = typeinfo_in_lib_p (type); tree var_desc, var_init; gcc_assert (DECL_TINFO_P (decl)); if (in_library) { if (doing_runtime) DECL_EXTERNAL (decl) = 0; else { /* If we're not in the runtime, then DECL (which is already DECL_EXTERNAL) will not be defined here. */ DECL_INTERFACE_KNOWN (decl) = 1; return false; } } else if (involves_incomplete_p (type)) { if (!decl_needed_p (decl)) return false; /* If TYPE involves an incomplete class type, then the typeinfo object will be emitted with internal linkage. There is no way to know whether or not types are incomplete until the end of the compilation, so this determination must be deferred until this point. */ TREE_PUBLIC (decl) = 0; DECL_EXTERNAL (decl) = 0; DECL_INTERFACE_KNOWN (decl) = 1; } import_export_decl (decl); if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl)) { DECL_EXTERNAL (decl) = 0; var_desc = get_pseudo_ti_desc (type); var_init = get_pseudo_ti_init (type, var_desc); DECL_INITIAL (decl) = var_init; mark_used (decl); cp_finish_decl (decl, var_init, NULL_TREE, 0); return true; } else return false; }
static tree make_alias_for_thunk (tree function) { tree alias; char buf[256]; #if defined (TARGET_IS_PE_COFF) if (DECL_ONE_ONLY (function)) return function; #endif ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); thunk_labelno++; alias = build_decl (FUNCTION_DECL, get_identifier (buf), TREE_TYPE (function)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (function); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_THIS_STATIC (alias) = 1; DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; DECL_PENDING_INLINE_P (alias) = 0; DECL_INLINE (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_DEFERRED_FN (alias) = 0; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INSTANTIATED (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; if (!flag_syntax_only) assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); return alias; }
void cxx_print_decl (FILE *file, tree node, int indent) { if (TREE_CODE (node) == FIELD_DECL) { if (DECL_MUTABLE_P (node)) { indent_to (file, indent + 3); fprintf (file, " mutable "); } return; } if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON) || !DECL_LANG_SPECIFIC (node)) return; if (TREE_CODE (node) == FUNCTION_DECL) { int flags = TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE |TFF_FUNCTION_DEFAULT_ARGUMENTS|TFF_EXCEPTION_SPECIFICATION ; indent_to (file, indent + 3); fprintf (file, " full-name \"%s\"", decl_as_string (node, flags)); } else if (TREE_CODE (node) == TEMPLATE_DECL) { indent_to (file, indent + 3); fprintf (file, " full-name \"%s\"", decl_as_string (node, TFF_TEMPLATE_HEADER)); } indent_to (file, indent + 3); if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node)) fprintf (file, " not-really-extern"); if (TREE_CODE (node) == FUNCTION_DECL && DECL_PENDING_INLINE_INFO (node)) fprintf (file, " pending-inline-info %p", (void *) DECL_PENDING_INLINE_INFO (node)); if (VAR_OR_FUNCTION_DECL_P (node) && DECL_TEMPLATE_INFO (node)) fprintf (file, " template-info %p", (void *) DECL_TEMPLATE_INFO (node)); }
tree make_alias_for (tree target, tree newid) { tree alias = build_decl (DECL_SOURCE_LOCATION (target), TREE_CODE (target), newid, TREE_TYPE (target)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (target); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; if (DECL_LANG_SPECIFIC (alias)) { DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; } DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_TEMPLATE_INSTANTIATED (alias) = 0; if (TREE_CODE (alias) == FUNCTION_DECL) { DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_PENDING_INLINE_P (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_INITIAL (alias) = error_mark_node; DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target)); } else TREE_STATIC (alias) = 1; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; return alias; }
void maybe_add_lambda_conv_op (tree type) { bool nested = (cfun != NULL); bool nested_def = decl_function_context (TYPE_MAIN_DECL (type)); tree callop = lambda_function (type); if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE) return; if (processing_template_decl) return; bool const generic_lambda_p = (DECL_TEMPLATE_INFO (callop) && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop); if (!generic_lambda_p && DECL_INITIAL (callop) == NULL_TREE) { /* If the op() wasn't instantiated due to errors, give up. */ gcc_assert (errorcount || sorrycount); return; } /* Non-template conversion operators are defined directly with build_call_a and using DIRECT_ARGVEC for arguments (including 'this'). Templates are deferred and the CALL is built in-place. In the case of a deduced return call op, the decltype expression, DECLTYPE_CALL, used as a substitute for the return type is also built in-place. The arguments of DECLTYPE_CALL in the return expression may differ in flags from those in the body CALL. In particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in the body CALL, but not in DECLTYPE_CALL. */ vec<tree, va_gc> *direct_argvec = 0; tree decltype_call = 0, call = 0; tree fn_result = TREE_TYPE (TREE_TYPE (callop)); if (generic_lambda_p) { /* Prepare the dependent member call for the static member function '_FUN' and, potentially, prepare another call to be used in a decltype return expression for a deduced return call op to allow for simple implementation of the conversion operator. */ tree instance = build_nop (type, null_pointer_node); tree objfn = build_min (COMPONENT_REF, NULL_TREE, instance, DECL_NAME (callop), NULL_TREE); int nargs = list_length (DECL_ARGUMENTS (callop)) - 1; call = prepare_op_call (objfn, nargs); if (type_uses_auto (fn_result)) decltype_call = prepare_op_call (objfn, nargs); } else { direct_argvec = make_tree_vector (); direct_argvec->quick_push (build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), null_pointer_node)); } /* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to declare the static member function "_FUN" below. For each arg append to DIRECT_ARGVEC (for the non-template case) or populate the pre-allocated call args (for the template case). If a parameter pack is found, expand it, flagging it as PACK_EXPANSION_LOCAL_P for the body call. */ tree fn_args = NULL_TREE; { int ix = 0; tree src = DECL_CHAIN (DECL_ARGUMENTS (callop)); tree tgt; while (src) { tree new_node = copy_node (src); if (!fn_args) fn_args = tgt = new_node; else { TREE_CHAIN (tgt) = new_node; tgt = new_node; } mark_exp_read (tgt); if (generic_lambda_p) { if (DECL_PACK_P (tgt)) { tree a = make_pack_expansion (tgt); if (decltype_call) CALL_EXPR_ARG (decltype_call, ix) = copy_node (a); PACK_EXPANSION_LOCAL_P (a) = true; CALL_EXPR_ARG (call, ix) = a; } else { tree a = convert_from_reference (tgt); CALL_EXPR_ARG (call, ix) = a; if (decltype_call) CALL_EXPR_ARG (decltype_call, ix) = copy_node (a); } ++ix; } else vec_safe_push (direct_argvec, tgt); src = TREE_CHAIN (src); } } if (generic_lambda_p) { if (decltype_call) { ++processing_template_decl; fn_result = finish_decltype_type (decltype_call, /*id_expression_or_member_access_p=*/false, tf_warning_or_error); --processing_template_decl; } } else call = build_call_a (callop, direct_argvec->length (), direct_argvec->address ()); CALL_FROM_THUNK_P (call) = 1; tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop)); /* First build up the conversion op. */ tree rettype = build_pointer_type (stattype); tree name = mangle_conv_op_name_for_type (rettype); tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST); tree fntype = build_method_type_directly (thistype, rettype, void_list_node); tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype); tree fn = convfn; DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR); grokclassfn (type, fn, NO_SPECIAL); set_linkage_according_to_type (type, fn); rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST); if (nested_def) DECL_INTERFACE_KNOWN (fn) = 1; if (generic_lambda_p) fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); add_method (type, fn, NULL_TREE); /* Generic thunk code fails for varargs; we'll complain in mark_used if the conversion op is used. */ if (varargs_function_p (callop)) { DECL_DELETED_FN (fn) = 1; return; } /* Now build up the thunk to be returned. */ name = get_identifier ("_FUN"); tree statfn = build_lang_decl (FUNCTION_DECL, name, stattype); fn = statfn; DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; grokclassfn (type, fn, NO_SPECIAL); set_linkage_according_to_type (type, fn); rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_STATIC_FUNCTION_P (fn) = 1; DECL_ARGUMENTS (fn) = fn_args; for (tree arg = fn_args; arg; arg = DECL_CHAIN (arg)) { /* Avoid duplicate -Wshadow warnings. */ DECL_NAME (arg) = NULL_TREE; DECL_CONTEXT (arg) = fn; } if (nested_def) DECL_INTERFACE_KNOWN (fn) = 1; if (generic_lambda_p) fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); add_method (type, fn, NULL_TREE); if (nested) push_function_context (); else /* Still increment function_depth so that we don't GC in the middle of an expression. */ ++function_depth; /* Generate the body of the thunk. */ start_preparsed_function (statfn, NULL_TREE, SF_PRE_PARSED | SF_INCLASS_INLINE); if (DECL_ONE_ONLY (statfn)) { /* Put the thunk in the same comdat group as the call op. */ cgraph_node::get_create (statfn)->add_to_same_comdat_group (cgraph_node::get_create (callop)); } tree body = begin_function_body (); tree compound_stmt = begin_compound_stmt (0); if (!generic_lambda_p) { set_flags_from_callee (call); if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error); } call = convert_from_reference (call); finish_return_stmt (call); finish_compound_stmt (compound_stmt); finish_function_body (body); fn = finish_function (/*inline*/2); if (!generic_lambda_p) expand_or_defer_fn (fn); /* Generate the body of the conversion op. */ start_preparsed_function (convfn, NULL_TREE, SF_PRE_PARSED | SF_INCLASS_INLINE); body = begin_function_body (); compound_stmt = begin_compound_stmt (0); /* decl_needed_p needs to see that it's used. */ TREE_USED (statfn) = 1; finish_return_stmt (decay_conversion (statfn, tf_warning_or_error)); finish_compound_stmt (compound_stmt); finish_function_body (body); fn = finish_function (/*inline*/2); if (!generic_lambda_p) expand_or_defer_fn (fn); if (nested) pop_function_context (); else --function_depth; }
tree make_thunk (tree function, bool this_adjusting, tree fixed_offset, tree virtual_offset) { HOST_WIDE_INT d; tree thunk; gcc_assert (TREE_CODE (function) == FUNCTION_DECL); /* We can have this thunks to covariant thunks, but not vice versa. */ gcc_assert (!DECL_THIS_THUNK_P (function)); gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting); /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ if (this_adjusting && virtual_offset) virtual_offset = size_binop (MULT_EXPR, virtual_offset, convert (ssizetype, TYPE_SIZE_UNIT (vtable_entry_type))); d = tree_low_cst (fixed_offset, 0); /* See if we already have the thunk in question. For this_adjusting thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it will be a BINFO. */ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk)) if (DECL_THIS_THUNK_P (thunk) == this_adjusting && THUNK_FIXED_OFFSET (thunk) == d && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk) && (!virtual_offset || (this_adjusting ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk), virtual_offset) : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset))) return thunk; /* All thunks must be created before FUNCTION is actually emitted; the ABI requires that all thunks be emitted together with the function to which they transfer control. */ gcc_assert (!TREE_ASM_WRITTEN (function)); /* Likewise, we can only be adding thunks to a function declared in the class currently being laid out. */ gcc_assert (TYPE_SIZE (DECL_CONTEXT (function)) && TYPE_BEING_DEFINED (DECL_CONTEXT (function))); thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (thunk); DECL_THUNKS (thunk) = NULL_TREE; DECL_CONTEXT (thunk) = DECL_CONTEXT (function); TREE_READONLY (thunk) = TREE_READONLY (function); TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (thunk) = TREE_PUBLIC (function); SET_DECL_THUNK_P (thunk, this_adjusting); THUNK_TARGET (thunk) = function; THUNK_FIXED_OFFSET (thunk) = d; THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset; THUNK_ALIAS (thunk) = NULL_TREE; /* The thunk itself is not a constructor or destructor, even if the thing it is thunking to is. */ DECL_INTERFACE_KNOWN (thunk) = 1; DECL_NOT_REALLY_EXTERN (thunk) = 1; DECL_SAVED_FUNCTION_DATA (thunk) = NULL; DECL_DESTRUCTOR_P (thunk) = 0; DECL_CONSTRUCTOR_P (thunk) = 0; DECL_EXTERNAL (thunk) = 1; DECL_ARTIFICIAL (thunk) = 1; /* Even if this thunk is a member of a local class, we don't need a static chain. */ DECL_NO_STATIC_CHAIN (thunk) = 1; /* The THUNK is not a pending inline, even if the FUNCTION is. */ DECL_PENDING_INLINE_P (thunk) = 0; DECL_INLINE (thunk) = 0; DECL_DECLARED_INLINE_P (thunk) = 0; /* Nor has it been deferred. */ DECL_DEFERRED_FN (thunk) = 0; /* Nor is it a template instantiation. */ DECL_USE_TEMPLATE (thunk) = 0; DECL_TEMPLATE_INFO (thunk) = NULL; /* Add it to the list of thunks associated with FUNCTION. */ TREE_CHAIN (thunk) = DECL_THUNKS (function); DECL_THUNKS (function) = thunk; return thunk; }
bool maybe_clone_body (tree fn) { tree clone; bool first = true; /* APPLE LOCAL begin ARM structor thunks */ tree clone_to_call; struct clone_info info; /* APPLE LOCAL end ARM structor thunks */ /* We only clone constructors and destructors. */ if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) return 0; /* Emit the DWARF1 abstract instance. */ (*debug_hooks->deferred_inline_function) (fn); /* APPLE LOCAL begin ARM structor thunks */ /* Figure out whether we can use the 'thunk' implementation, and if so on which clones. */ info.next_clone = 0; info.which_thunks_ok = compute_use_thunks (fn); /* APPLE LOCAL end ARM structor thunks */ /* We know that any clones immediately follow FN in the TYPE_METHODS list. */ push_to_top_level (); FOR_EACH_CLONE (clone, fn) { tree parm; tree clone_parm; int parmno; splay_tree decl_map; /* Update CLONE's source position information to match FN's. */ DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); DECL_INLINE (clone) = DECL_INLINE (fn); DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); /* LLVM LOCAL begin inlinehint attribute */ DECL_EXPLICIT_INLINE_P (clone) = DECL_EXPLICIT_INLINE_P (fn); /* LLVM LOCAL end inlinehint attribute */ DECL_COMDAT (clone) = DECL_COMDAT (fn); DECL_WEAK (clone) = DECL_WEAK (fn); DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn); DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn); DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn); DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn); DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn); DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn); TREE_PUBLIC (clone) = TREE_PUBLIC (fn); DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn); DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn); /* Adjust the parameter names and locations. */ parm = DECL_ARGUMENTS (fn); clone_parm = DECL_ARGUMENTS (clone); /* Update the `this' parameter, which is always first. */ update_cloned_parm (parm, clone_parm, first); parm = TREE_CHAIN (parm); clone_parm = TREE_CHAIN (clone_parm); if (DECL_HAS_IN_CHARGE_PARM_P (fn)) parm = TREE_CHAIN (parm); if (DECL_HAS_VTT_PARM_P (fn)) parm = TREE_CHAIN (parm); if (DECL_HAS_VTT_PARM_P (clone)) clone_parm = TREE_CHAIN (clone_parm); for (; parm; parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm)) /* Update this parameter. */ update_cloned_parm (parm, clone_parm, first); /* Start processing the function. */ start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); /* Remap the parameters. */ decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); for (parmno = 0, parm = DECL_ARGUMENTS (fn), clone_parm = DECL_ARGUMENTS (clone); parm; ++parmno, parm = TREE_CHAIN (parm)) { /* Map the in-charge parameter to an appropriate constant. */ if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) { tree in_charge; in_charge = in_charge_arg_for_name (DECL_NAME (clone)); splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) in_charge); /* APPLE LOCAL ARM structor thunks */ info.in_charge_value [info.next_clone] = in_charge; } else if (DECL_ARTIFICIAL (parm) && DECL_NAME (parm) == vtt_parm_identifier) { /* For a subobject constructor or destructor, the next argument is the VTT parameter. Remap the VTT_PARM from the CLONE to this parameter. */ if (DECL_HAS_VTT_PARM_P (clone)) { DECL_ABSTRACT_ORIGIN (clone_parm) = parm; splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) clone_parm); clone_parm = TREE_CHAIN (clone_parm); } /* Otherwise, map the VTT parameter to `NULL'. */ else { splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) null_pointer_node); } } /* Map other parameters to their equivalents in the cloned function. */ else { splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) clone_parm); clone_parm = TREE_CHAIN (clone_parm); } } if (targetm.cxx.cdtor_returns_this ()) { parm = DECL_RESULT (fn); clone_parm = DECL_RESULT (clone); splay_tree_insert (decl_map, (splay_tree_key) parm, (splay_tree_value) clone_parm); } /* APPLE LOCAL begin ARM structor thunks */ clone_to_call = find_earlier_clone (&info); if (clone_to_call) /* Bodies are identical; replace later one with call to an earlier one. */ thunk_body (clone, fn, clone_to_call); else /* Clone the body. */ clone_body (clone, fn, decl_map); /* APPLE LOCAL end ARM structor thunks */ /* The clone can throw iff the original function can throw. */ cp_function_chain->can_throw = !TREE_NOTHROW (fn); /* Now, expand this function into RTL, if appropriate. */ finish_function (0); BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); expand_or_defer_fn (clone); first = false; /* APPLE LOCAL begin ARM structor thunks */ info.clones [info.next_clone] = clone; info.next_clone++; /* APPLE LOCAL end ARM structor thunks */ }