void cp_genericize (tree fndecl) { tree t; struct pointer_set_t *p_set; /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) if (TREE_ADDRESSABLE (TREE_TYPE (t))) { /* If a function's arguments are copied to create a thunk, then DECL_BY_REFERENCE will be set -- but the type of the argument will be a pointer type, so we will never get here. */ gcc_assert (!DECL_BY_REFERENCE (t)); gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); TREE_TYPE (t) = DECL_ARG_TYPE (t); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) { t = DECL_RESULT (fndecl); TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* If we're a clone, the body is already GIMPLE. */ if (DECL_CLONED_FUNCTION_P (fndecl)) return; /* We do want to see every occurrence of the parms, so we can't just use walk_tree's hash functionality. */ p_set = pointer_set_create (); cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); pointer_set_destroy (p_set); /* Do everything else. */ c_genericize (fndecl); gcc_assert (bc_label[bc_break] == NULL); gcc_assert (bc_label[bc_continue] == NULL); }
void synthesize_method (tree fndecl) { bool nested = (current_function_decl != NULL_TREE); tree context = decl_function_context (fndecl); bool need_body = true; tree stmt; location_t save_input_location = input_location; int error_count = errorcount; int warning_count = warningcount; /* Reset the source location, we might have been previously deferred, and thus have saved where we were first needed. */ DECL_SOURCE_LOCATION (fndecl) = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl))); /* If we've been asked to synthesize a clone, just synthesize the cloned function instead. Doing so will automatically fill in the body for the clone. */ if (DECL_CLONED_FUNCTION_P (fndecl)) fndecl = DECL_CLONED_FUNCTION (fndecl); /* We may be in the middle of deferred access check. Disable it now. */ push_deferring_access_checks (dk_no_deferred); if (! context) push_to_top_level (); else if (nested) push_function_context_to (context); input_location = DECL_SOURCE_LOCATION (fndecl); start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); stmt = begin_function_body (); if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) { do_build_assign_ref (fndecl); need_body = false; } else if (DECL_CONSTRUCTOR_P (fndecl)) { tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else finish_mem_initializers (NULL_TREE); } /* If we haven't yet generated the body of the function, just generate an empty compound statement. */ if (need_body) { tree compound_stmt; compound_stmt = begin_compound_stmt (BCS_FN_BODY); finish_compound_stmt (compound_stmt); } finish_function_body (stmt); expand_or_defer_fn (finish_function (0)); input_location = save_input_location; if (! context) pop_from_top_level (); else if (nested) pop_function_context_from (context); pop_deferring_access_checks (); if (error_count != errorcount || warning_count != warningcount) inform ("%Hsynthesized method %qD first required here ", &input_location, fndecl); }
void cp_genericize (tree fndecl) { tree t; /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t)) if (TREE_ADDRESSABLE (TREE_TYPE (t))) { /* If a function's arguments are copied to create a thunk, then DECL_BY_REFERENCE will be set -- but the type of the argument will be a pointer type, so we will never get here. */ gcc_assert (!DECL_BY_REFERENCE (t)); gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); TREE_TYPE (t) = DECL_ARG_TYPE (t); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) { t = DECL_RESULT (fndecl); TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); if (DECL_NAME (t)) { /* Adjust DECL_VALUE_EXPR of the original var. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) if (DECL_NAME (t) == DECL_NAME (var) && DECL_HAS_VALUE_EXPR_P (var) && DECL_VALUE_EXPR (var) == t) { tree val = convert_from_reference (t); SET_DECL_VALUE_EXPR (var, val); break; } } } /* If we're a clone, the body is already GIMPLE. */ if (DECL_CLONED_FUNCTION_P (fndecl)) return; /* Expand all the array notations here. */ if (flag_enable_cilkplus && contains_array_notation_expr (DECL_SAVED_TREE (fndecl))) DECL_SAVED_TREE (fndecl) = expand_array_notation_exprs (DECL_SAVED_TREE (fndecl)); /* We do want to see every occurrence of the parms, so we can't just use walk_tree's hash functionality. */ cp_genericize_tree (&DECL_SAVED_TREE (fndecl)); if (flag_sanitize & SANITIZE_RETURN) cp_ubsan_maybe_instrument_return (fndecl); /* Do everything else. */ c_genericize (fndecl); gcc_assert (bc_label[bc_break] == NULL); gcc_assert (bc_label[bc_continue] == NULL); }
void gcc_cp_genericize (tree fndecl) { register_src_file(fndecl); tree t; struct cp_genericize_data wtd; /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t)) if (TREE_ADDRESSABLE (TREE_TYPE (t))) { /* If a function's arguments are copied to create a thunk, then DECL_BY_REFERENCE will be set -- but the type of the argument will be a pointer type, so we will never get here. */ gcc_assert (!DECL_BY_REFERENCE (t)); gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); TREE_TYPE (t) = DECL_ARG_TYPE (t); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) { t = DECL_RESULT (fndecl); TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); if (DECL_NAME (t)) { /* Adjust DECL_VALUE_EXPR of the original var. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) if (DECL_NAME (t) == DECL_NAME (var) && DECL_HAS_VALUE_EXPR_P (var) && DECL_VALUE_EXPR (var) == t) { tree val = convert_from_reference (t); SET_DECL_VALUE_EXPR (var, val); break; } } } /* If we're a clone, the body is already GIMPLE. */ if (DECL_CLONED_FUNCTION_P (fndecl)) return; /* We do want to see every occurrence of the parms, so we can't just use walk_tree's hash functionality. */ wtd.p_set = pointer_set_create (); wtd.bind_expr_stack = NULL; cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL); pointer_set_destroy (wtd.p_set); VEC_free (tree, heap, wtd.bind_expr_stack); /* Do everything else. */ gcc_genericize (fndecl); gcc_assert (bc_label[bc_break] == NULL); gcc_assert (bc_label[bc_continue] == NULL); }
void synthesize_method (tree fndecl) { bool nested = (current_function_decl != NULL_TREE); tree context = decl_function_context (fndecl); bool need_body = true; tree stmt; if (at_eof) import_export_decl (fndecl); /* If we've been asked to synthesize a clone, just synthesize the cloned function instead. Doing so will automatically fill in the body for the clone. */ if (DECL_CLONED_FUNCTION_P (fndecl)) { synthesize_method (DECL_CLONED_FUNCTION (fndecl)); return; } /* We may be in the middle of deferred access check. Disable it now. */ push_deferring_access_checks (dk_no_deferred); if (! context) push_to_top_level (); else if (nested) push_function_context_to (context); /* Put the function definition at the position where it is needed, rather than within the body of the class. That way, an error during the generation of the implicit body points at the place where the attempt to generate the function occurs, giving the user a hint as to why we are attempting to generate the function. */ DECL_SOURCE_LOCATION (fndecl) = input_location; interface_unknown = 1; start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); clear_last_expr (); stmt = begin_function_body (); if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) { do_build_assign_ref (fndecl); need_body = false; } else if (DECL_CONSTRUCTOR_P (fndecl)) { tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) finish_mem_initializers (NULL_TREE); } /* If we haven't yet generated the body of the function, just generate an empty compound statement. */ if (need_body) { tree compound_stmt; compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); finish_compound_stmt (compound_stmt); } finish_function_body (stmt); expand_or_defer_fn (finish_function (0)); extract_interface_info (); if (! context) pop_from_top_level (); else if (nested) pop_function_context_from (context); pop_deferring_access_checks (); }