X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finfcall.c;h=b2f8ed21dc92d10830f283c499887ec51ecc207f;hb=268a13a5a3f7c6b9b6ffc5ac2d1b24eb41f3fbdc;hp=e1861dcd8e1f5617bb5350b650676e7f354bea79;hpb=00431a78b28f913a9d5c912c49680e39cfd20847;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcall.c b/gdb/infcall.c index e1861dcd8e..b2f8ed21dc 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -1,6 +1,6 @@ /* Perform an inferior function call, for GDB, the GNU debugger. - Copyright (C) 1986-2018 Free Software Foundation, Inc. + Copyright (C) 1986-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -33,6 +33,7 @@ #include "command.h" #include "dummy-frame.h" #include "ada-lang.h" +#include "f-lang.h" #include "gdbthread.h" #include "event-top.h" #include "observable.h" @@ -40,6 +41,7 @@ #include "interps.h" #include "thread-fsm.h" #include +#include "gdbsupport/scope-exit.h" /* If we can't find a function's name from its address, we print this instead. */ @@ -53,6 +55,17 @@ asynchronous inferior function call implementation, and that in turn means restructuring the code so that it is event driven. */ +static int may_call_functions_p = 1; +static void +show_may_call_functions_p (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, + _("Permission to call functions in the program is %s.\n"), + value); +} + /* How you should pass arguments to a function depends on whether it was defined in K&R style or prototype style. If you define a function using the K&R syntax that takes a `float' argument, then @@ -129,7 +142,7 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty, } /* Perform the standard coercions that are specified - for arguments to be passed to C or Ada functions. + for arguments to be passed to C, Ada or Fortran functions. If PARAM_TYPE is non-NULL, it is the expected parameter type. IS_PROTOTYPED is non-zero if the function declaration is prototyped. @@ -145,9 +158,11 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, struct type *type = param_type ? check_typedef (param_type) : arg_type; - /* Perform any Ada-specific coercion first. */ + /* Perform any Ada- and Fortran-specific coercion first. */ if (current_language->la_language == language_ada) arg = ada_convert_actual (arg, type); + else if (current_language->la_language == language_fortran) + type = fortran_preserve_arg_pointer (arg, type); /* Force the value to the target if we will need its address. At this point, we could allocate arguments on the stack instead of @@ -334,7 +349,7 @@ find_function_addr (struct value *function, static CORE_ADDR push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr, - struct value **args, int nargs, + gdb::array_view args, struct type *value_type, CORE_ADDR *real_pc, CORE_ADDR *bp_addr, struct regcache *regcache) @@ -342,7 +357,8 @@ push_dummy_code (struct gdbarch *gdbarch, gdb_assert (gdbarch_push_dummy_code_p (gdbarch)); return gdbarch_push_dummy_code (gdbarch, sp, funaddr, - args, nargs, value_type, real_pc, bp_addr, + args.data (), args.size (), + value_type, real_pc, bp_addr, regcache); } @@ -385,13 +401,11 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) } { - char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT), - hex_string (funaddr)); + std::string tmp = string_printf (_(RAW_FUNCTION_ADDRESS_FORMAT), + hex_string (funaddr)); - gdb_assert (strlen (tmp) + 1 <= buf_size); - strcpy (buf, tmp); - xfree (tmp); - return buf; + gdb_assert (tmp.length () + 1 <= buf_size); + return strcpy (buf, tmp.c_str ()); } } @@ -470,106 +484,87 @@ get_call_return_value (struct call_return_meta_info *ri) /* Data for the FSM that manages an infcall. It's main job is to record the called function's return value. */ -struct call_thread_fsm +struct call_thread_fsm : public thread_fsm { - /* The base class. */ - struct thread_fsm thread_fsm; - /* All the info necessary to be able to extract the return value. */ struct call_return_meta_info return_meta_info; /* The called function's return value. This is extracted from the target before the dummy frame is popped. */ - struct value *return_value; + struct value *return_value = nullptr; /* The top level that started the infcall (and is synchronously waiting for it to end). */ struct ui *waiting_ui; -}; -static int call_thread_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread); -static int call_thread_fsm_should_notify_stop (struct thread_fsm *self); + call_thread_fsm (struct ui *waiting_ui, struct interp *cmd_interp, + struct gdbarch *gdbarch, struct value *function, + struct type *value_type, + int struct_return_p, CORE_ADDR struct_addr); -/* call_thread_fsm's vtable. */ + bool should_stop (struct thread_info *thread) override; -static struct thread_fsm_ops call_thread_fsm_ops = -{ - NULL, /*dtor */ - NULL, /* clean_up */ - call_thread_fsm_should_stop, - NULL, /* return_value */ - NULL, /* async_reply_reason*/ - call_thread_fsm_should_notify_stop, + bool should_notify_stop () override; }; /* Allocate a new call_thread_fsm object. */ -static struct call_thread_fsm * -new_call_thread_fsm (struct ui *waiting_ui, struct interp *cmd_interp, - struct gdbarch *gdbarch, struct value *function, - struct type *value_type, - int struct_return_p, CORE_ADDR struct_addr) +call_thread_fsm::call_thread_fsm (struct ui *waiting_ui, + struct interp *cmd_interp, + struct gdbarch *gdbarch, + struct value *function, + struct type *value_type, + int struct_return_p, CORE_ADDR struct_addr) + : thread_fsm (cmd_interp), + waiting_ui (waiting_ui) { - struct call_thread_fsm *sm; - - sm = XCNEW (struct call_thread_fsm); - thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops, cmd_interp); - - sm->return_meta_info.gdbarch = gdbarch; - sm->return_meta_info.function = function; - sm->return_meta_info.value_type = value_type; - sm->return_meta_info.struct_return_p = struct_return_p; - sm->return_meta_info.struct_addr = struct_addr; - - sm->waiting_ui = waiting_ui; - - return sm; + return_meta_info.gdbarch = gdbarch; + return_meta_info.function = function; + return_meta_info.value_type = value_type; + return_meta_info.struct_return_p = struct_return_p; + return_meta_info.struct_addr = struct_addr; } /* Implementation of should_stop method for infcalls. */ -static int -call_thread_fsm_should_stop (struct thread_fsm *self, - struct thread_info *thread) +bool +call_thread_fsm::should_stop (struct thread_info *thread) { - struct call_thread_fsm *f = (struct call_thread_fsm *) self; - if (stop_stack_dummy == STOP_STACK_DUMMY) { /* Done. */ - thread_fsm_set_finished (self); + set_finished (); /* Stash the return value before the dummy frame is popped and registers are restored to what they were before the call.. */ - f->return_value = get_call_return_value (&f->return_meta_info); + return_value = get_call_return_value (&return_meta_info); /* Break out of wait_sync_command_done. */ - scoped_restore save_ui = make_scoped_restore (¤t_ui, f->waiting_ui); + scoped_restore save_ui = make_scoped_restore (¤t_ui, waiting_ui); target_terminal::ours (); - f->waiting_ui->prompt_state = PROMPT_NEEDED; + waiting_ui->prompt_state = PROMPT_NEEDED; } - return 1; + return true; } /* Implementation of should_notify_stop method for infcalls. */ -static int -call_thread_fsm_should_notify_stop (struct thread_fsm *self) +bool +call_thread_fsm::should_notify_stop () { - if (thread_fsm_finished_p (self)) + if (finished_p ()) { /* Infcall succeeded. Be silent and proceed with evaluating the expression. */ - return 0; + return false; } /* Something wrong happened. E.g., an unexpected breakpoint triggered, or a signal was intercepted. Notify the stop. */ - return 1; + return true; } /* Subroutine of call_function_by_hand to simplify it. @@ -584,10 +579,9 @@ static struct gdb_exception run_inferior_call (struct call_thread_fsm *sm, struct thread_info *call_thread, CORE_ADDR real_pc) { - struct gdb_exception caught_error = exception_none; + struct gdb_exception caught_error; int saved_in_infcall = call_thread->control.in_infcall; ptid_t call_thread_ptid = call_thread->ptid; - inferior *call_thread_inf = call_thread->inf; enum prompt_state saved_prompt_state = current_ui->prompt_state; int was_running = call_thread->state == THREAD_RUNNING; int saved_ui_async = current_ui->async; @@ -607,14 +601,14 @@ run_inferior_call (struct call_thread_fsm *sm, /* Associate the FSM with the thread after clear_proceed_status (otherwise it'd clear this FSM), and before anything throws, so we don't leak it (and any resources it manages). */ - call_thread->thread_fsm = &sm->thread_fsm; + call_thread->thread_fsm = sm; disable_watchpoints_before_interactive_call_start (); /* We want to print return value, please... */ call_thread->control.proceed_to_finish = 1; - TRY + try { proceed (real_pc, GDB_SIGNAL_0); @@ -622,11 +616,10 @@ run_inferior_call (struct call_thread_fsm *sm, target supports asynchronous execution. */ wait_sync_command_done (); } - CATCH (e, RETURN_MASK_ALL) + catch (gdb_exception &e) { - caught_error = e; + caught_error = std::move (e); } - END_CATCH /* If GDB has the prompt blocked before, then ensure that it remains so. normal_stop calls async_enable_stdin, so reset the prompt @@ -677,22 +670,15 @@ run_inferior_call (struct call_thread_fsm *sm, return caught_error; } -/* A cleanup function that calls delete_std_terminate_breakpoint. */ -static void -cleanup_delete_std_terminate_breakpoint (void *ignore) -{ - delete_std_terminate_breakpoint (); -} - /* See infcall.h. */ struct value * call_function_by_hand (struct value *function, type *default_return_type, - int nargs, struct value **args) + gdb::array_view args) { return call_function_by_hand_dummy (function, default_return_type, - nargs, args, NULL, NULL); + args, NULL, NULL); } /* All this stuff with a dummy frame may seem unnecessarily complicated @@ -716,27 +702,27 @@ call_function_by_hand (struct value *function, struct value * call_function_by_hand_dummy (struct value *function, type *default_return_type, - int nargs, struct value **args, + gdb::array_view args, dummy_frame_dtor_ftype *dummy_dtor, void *dummy_dtor_data) { CORE_ADDR sp; struct type *target_values_type; - unsigned char struct_return = 0, hidden_first_param_p = 0; + function_call_return_method return_method = return_method_normal; CORE_ADDR struct_addr = 0; - struct infcall_control_state *inf_status; - struct cleanup *inf_status_cleanup; - struct infcall_suspend_state *caller_state; CORE_ADDR real_pc; CORE_ADDR bp_addr; struct frame_id dummy_id; struct frame_info *frame; struct gdbarch *gdbarch; - struct cleanup *terminate_bp_cleanup; ptid_t call_thread_ptid; struct gdb_exception e; char name_buf[RAW_FUNCTION_ADDRESS_SIZE]; + if (!may_call_functions_p) + error (_("Cannot call functions in the program: " + "may-call-functions is off.")); + if (!target_has_execution) noprocess (); @@ -760,19 +746,16 @@ call_function_by_hand_dummy (struct value *function, if (!gdbarch_push_dummy_call_p (gdbarch)) error (_("This target does not support function calls.")); - /* A cleanup for the inferior status. + /* A holder for the inferior status. This is only needed while we're preparing the inferior function call. */ - inf_status = save_infcall_control_state (); - inf_status_cleanup - = make_cleanup_restore_infcall_control_state (inf_status); + infcall_control_state_up inf_status (save_infcall_control_state ()); /* Save the caller's registers and other state associated with the inferior itself so that they can be restored once the callee returns. To allow nested calls the registers are (further - down) pushed onto a dummy frame stack. Include a cleanup (which - is tossed once the regcache has been pushed). */ - caller_state = save_infcall_suspend_state (); - make_cleanup_restore_infcall_suspend_state (caller_state); + down) pushed onto a dummy frame stack. This unique pointer + is released once the regcache has been pushed). */ + infcall_suspend_state_up caller_state (save_infcall_suspend_state ()); /* Ensure that the initial SP is correctly aligned. */ { @@ -885,20 +868,11 @@ call_function_by_hand_dummy (struct value *function, values_type = check_typedef (values_type); - /* Are we returning a value using a structure return (passing a - hidden argument pointing to storage) or a normal value return? - There are two cases: language-mandated structure return and - target ABI structure return. The variable STRUCT_RETURN only - describes the latter. The language version is handled by passing - the return location as the first parameter to the function, - even preceding "this". This is different from the target - ABI version, which is target-specific; for instance, on ia64 - the first argument is passed in out0 but the hidden structure - return pointer would normally be passed in r8. */ + /* Are we returning a value using a structure return? */ if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type)) { - hidden_first_param_p = 1; + return_method = return_method_hidden_param; /* Tell the target specific argument pushing routine not to expect a value. */ @@ -906,7 +880,8 @@ call_function_by_hand_dummy (struct value *function, } else { - struct_return = using_struct_return (gdbarch, function, values_type); + if (using_struct_return (gdbarch, function, values_type)) + return_method = return_method_struct; target_values_type = values_type; } @@ -929,7 +904,7 @@ call_function_by_hand_dummy (struct value *function, /* Be careful BP_ADDR is in inferior PC encoding while BP_ADDR_AS_ADDRESS is a plain memory address. */ - sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs, + sp = push_dummy_code (gdbarch, sp, funaddr, args, target_values_type, &real_pc, &bp_addr, get_current_regcache ()); @@ -970,53 +945,49 @@ call_function_by_hand_dummy (struct value *function, internal_error (__FILE__, __LINE__, _("bad switch")); } - if (nargs < TYPE_NFIELDS (ftype)) + if (args.size () < TYPE_NFIELDS (ftype)) error (_("Too few arguments in function call.")); - { - int i; - - for (i = nargs - 1; i >= 0; i--) - { - int prototyped; - struct type *param_type; - - /* FIXME drow/2002-05-31: Should just always mark methods as - prototyped. Can we respect TYPE_VARARGS? Probably not. */ - if (TYPE_CODE (ftype) == TYPE_CODE_METHOD) + for (int i = args.size () - 1; i >= 0; i--) + { + int prototyped; + struct type *param_type; + + /* FIXME drow/2002-05-31: Should just always mark methods as + prototyped. Can we respect TYPE_VARARGS? Probably not. */ + if (TYPE_CODE (ftype) == TYPE_CODE_METHOD) + prototyped = 1; + if (TYPE_TARGET_TYPE (ftype) == NULL && TYPE_NFIELDS (ftype) == 0 + && default_return_type != NULL) + { + /* Calling a no-debug function with the return type + explicitly cast. Assume the function is prototyped, + with a prototype matching the types of the arguments. + E.g., with: + float mult (float v1, float v2) { return v1 * v2; } + This: + (gdb) p (float) mult (2.0f, 3.0f) + Is a simpler alternative to: + (gdb) p ((float (*) (float, float)) mult) (2.0f, 3.0f) + */ prototyped = 1; - if (TYPE_TARGET_TYPE (ftype) == NULL && TYPE_NFIELDS (ftype) == 0 - && default_return_type != NULL) - { - /* Calling a no-debug function with the return type - explicitly cast. Assume the function is prototyped, - with a prototype matching the types of the arguments. - E.g., with: - float mult (float v1, float v2) { return v1 * v2; } - This: - (gdb) p (float) mult (2.0f, 3.0f) - Is a simpler alternative to: - (gdb) p ((float (*) (float, float)) mult) (2.0f, 3.0f) - */ - prototyped = 1; - } - else if (i < TYPE_NFIELDS (ftype)) - prototyped = TYPE_PROTOTYPED (ftype); - else - prototyped = 0; + } + else if (i < TYPE_NFIELDS (ftype)) + prototyped = TYPE_PROTOTYPED (ftype); + else + prototyped = 0; - if (i < TYPE_NFIELDS (ftype)) - param_type = TYPE_FIELD_TYPE (ftype, i); - else - param_type = NULL; + if (i < TYPE_NFIELDS (ftype)) + param_type = TYPE_FIELD_TYPE (ftype, i); + else + param_type = NULL; - args[i] = value_arg_coerce (gdbarch, args[i], - param_type, prototyped, &sp); + args[i] = value_arg_coerce (gdbarch, args[i], + param_type, prototyped, &sp); - if (param_type != NULL && language_pass_by_reference (param_type)) - args[i] = value_addr (args[i]); - } - } + if (param_type != NULL && language_pass_by_reference (param_type)) + args[i] = value_addr (args[i]); + } /* Reserve space for the return structure to be written on the stack, if necessary. Make certain that the value is correctly @@ -1033,7 +1004,7 @@ call_function_by_hand_dummy (struct value *function, is being evaluated is OK because the thread is stopped until the expression is completely evaluated. */ - if (struct_return || hidden_first_param_p + if (return_method != return_method_normal || (stack_temporaries && class_or_union_p (values_type))) { if (gdbarch_inner_than (gdbarch, 1, 2)) @@ -1059,22 +1030,22 @@ call_function_by_hand_dummy (struct value *function, } std::vector new_args; - if (hidden_first_param_p) + if (return_method == return_method_hidden_param) { /* Add the new argument to the front of the argument list. */ + new_args.reserve (args.size ()); new_args.push_back (value_from_pointer (lookup_pointer_type (values_type), struct_addr)); - std::copy (&args[0], &args[nargs], std::back_inserter (new_args)); - args = new_args.data (); - nargs++; + new_args.insert (new_args.end (), args.begin (), args.end ()); + args = new_args; } /* Create the dummy stack frame. Pass in the call dummy address as, presumably, the ABI code knows where, in the call dummy, the return address should be pointed. */ sp = gdbarch_push_dummy_call (gdbarch, function, get_current_regcache (), - bp_addr, nargs, args, - sp, struct_return, struct_addr); + bp_addr, args.size (), args.data (), + sp, return_method, struct_addr); /* Set up a frame ID for the dummy frame so we can pass it to set_momentary_breakpoint. We need to give the breakpoint a frame @@ -1133,22 +1104,16 @@ call_function_by_hand_dummy (struct value *function, if (unwind_on_terminating_exception_p) set_std_terminate_breakpoint (); - /* Discard both inf_status and caller_state cleanups. - From this point on we explicitly restore the associated state - or discard it. */ - discard_cleanups (inf_status_cleanup); - /* Everything's ready, push all the info needed to restore the caller (and identify the dummy-frame) onto the dummy-frame stack. */ - dummy_frame_push (caller_state, &dummy_id, call_thread.get ()); + dummy_frame_push (caller_state.release (), &dummy_id, call_thread.get ()); if (dummy_dtor != NULL) register_dummy_frame_dtor (dummy_id, call_thread.get (), dummy_dtor, dummy_dtor_data); /* Register a clean-up for unwind_on_terminating_exception_breakpoint. */ - terminate_bp_cleanup = make_cleanup (cleanup_delete_std_terminate_breakpoint, - NULL); + SCOPE_EXIT { delete_std_terminate_breakpoint (); }; /* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - If you're looking to implement asynchronous dummy-frames, then @@ -1172,10 +1137,10 @@ call_function_by_hand_dummy (struct value *function, not report the stop to the user, and captures the return value before the dummy frame is popped. run_inferior_call registers it with the thread ASAP. */ - sm = new_call_thread_fsm (current_ui, command_interp (), + sm = new call_thread_fsm (current_ui, command_interp (), gdbarch, function, values_type, - struct_return || hidden_first_param_p, + return_method != return_method_normal, struct_addr); e = run_inferior_call (sm, call_thread.get (), real_pc); @@ -1185,9 +1150,9 @@ call_function_by_hand_dummy (struct value *function, if (call_thread->state != THREAD_EXITED) { /* The FSM should still be the same. */ - gdb_assert (call_thread->thread_fsm == &sm->thread_fsm); + gdb_assert (call_thread->thread_fsm == sm); - if (thread_fsm_finished_p (call_thread->thread_fsm)) + if (call_thread->thread_fsm->finished_p ()) { struct value *retval; @@ -1196,26 +1161,27 @@ call_function_by_hand_dummy (struct value *function, suspend state, and restore the inferior control state. */ dummy_frame_pop (dummy_id, call_thread.get ()); - restore_infcall_control_state (inf_status); + restore_infcall_control_state (inf_status.release ()); /* Get the return value. */ retval = sm->return_value; /* Clean up / destroy the call FSM, and restore the original one. */ - thread_fsm_clean_up (call_thread->thread_fsm, call_thread.get ()); - thread_fsm_delete (call_thread->thread_fsm); + call_thread->thread_fsm->clean_up (call_thread.get ()); + delete call_thread->thread_fsm; call_thread->thread_fsm = saved_sm; maybe_remove_breakpoints (); - do_cleanups (terminate_bp_cleanup); gdb_assert (retval != NULL); return retval; } - /* Didn't complete. Restore previous state machine, and - handle the error. */ + /* Didn't complete. Clean up / destroy the call FSM, and restore the + previous state machine, and handle the error. */ + call_thread->thread_fsm->clean_up (call_thread.get ()); + delete call_thread->thread_fsm; call_thread->thread_fsm = saved_sm; } } @@ -1227,7 +1193,7 @@ call_function_by_hand_dummy (struct value *function, const char *name = get_function_name (funaddr, name_buf, sizeof (name_buf)); - discard_infcall_control_state (inf_status); + discard_infcall_control_state (inf_status.release ()); /* We could discard the dummy frame here if the program exited, but it will get garbage collected the next time the program is @@ -1241,10 +1207,10 @@ An error occurred while in a function called from GDB.\n\ Evaluation of the expression containing the function\n\ (%s) will be abandoned.\n\ When the function is done executing, GDB will silently stop."), - e.message, name); + e.what (), name); case RETURN_QUIT: default: - throw_exception (e); + throw_exception (std::move (e)); } } @@ -1258,7 +1224,7 @@ When the function is done executing, GDB will silently stop."), /* If we try to restore the inferior status, we'll crash as the inferior is no longer running. */ - discard_infcall_control_state (inf_status); + discard_infcall_control_state (inf_status.release ()); /* We could discard the dummy frame here given that the program exited, but it will get garbage collected the next time the program is @@ -1271,7 +1237,7 @@ When the function is done executing, GDB will silently stop."), name); } - if (! ptid_equal (call_thread_ptid, inferior_ptid)) + if (call_thread_ptid != inferior_ptid) { const char *name = get_function_name (funaddr, name_buf, sizeof (name_buf)); @@ -1280,7 +1246,7 @@ When the function is done executing, GDB will silently stop."), signal or breakpoint while our thread was running. There's no point in restoring the inferior status, we're in a different thread. */ - discard_infcall_control_state (inf_status); + discard_infcall_control_state (inf_status.release ()); /* Keep the dummy frame record, if the user switches back to the thread with the hand-call, we'll need it. */ if (stopped_by_random_signal) @@ -1321,7 +1287,7 @@ When the function is done executing, GDB will silently stop."), /* We also need to restore inferior status to that before the dummy call. */ - restore_infcall_control_state (inf_status); + restore_infcall_control_state (inf_status.release ()); /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ @@ -1339,7 +1305,7 @@ Evaluation of the expression containing the function\n\ (default). Discard inferior status, we're not at the same point we started at. */ - discard_infcall_control_state (inf_status); + discard_infcall_control_state (inf_status.release ()); /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ @@ -1362,7 +1328,7 @@ When the function is done executing, GDB will silently stop."), /* We also need to restore inferior status to that before the dummy call. */ - restore_infcall_control_state (inf_status); + restore_infcall_control_state (inf_status.release ()); error (_("\ The program being debugged entered a std::terminate call, most likely\n\ @@ -1381,7 +1347,7 @@ will be abandoned."), Keep the dummy frame, the user may want to examine its state. Discard inferior status, we're not at the same point we started at. */ - discard_infcall_control_state (inf_status); + discard_infcall_control_state (inf_status.release ()); /* The following error message used to say "The expression which contained the function call has been discarded." @@ -1408,6 +1374,17 @@ When the function is done executing, GDB will silently stop."), void _initialize_infcall (void) { + add_setshow_boolean_cmd ("may-call-functions", no_class, + &may_call_functions_p, _("\ +Set permission to call functions in the program."), _("\ +Show permission to call functions in the program."), _("\ +When this permission is on, GDB may call functions in the program.\n\ +Otherwise, any sort of attempt to call a function in the program\n\ +will result in an error."), + NULL, + show_may_call_functions_p, + &setlist, &showlist); + add_setshow_boolean_cmd ("coerce-float-to-double", class_obscure, &coerce_float_to_double_p, _("\ Set coercion of floats to doubles when calling functions."), _("\ @@ -1418,7 +1395,7 @@ function. However, some older debug info formats do not provide enough\n\ information to determine that a function is prototyped. If this flag is\n\ set, GDB will perform the conversion for a function it considers\n\ unprototyped.\n\ -The default is to perform the conversion.\n"), +The default is to perform the conversion."), NULL, show_coerce_float_to_double_p, &setlist, &showlist);