+ struct gdb_exception caught_error;
+ int saved_in_infcall = call_thread->control.in_infcall;
+ ptid_t call_thread_ptid = call_thread->ptid;
+ 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;
+
+ /* Infcalls run synchronously, in the foreground. */
+ current_ui->prompt_state = PROMPT_BLOCKED;
+ /* So that we don't print the prompt prematurely in
+ fetch_inferior_event. */
+ current_ui->async = 0;
+
+ delete_file_handler (current_ui->input_fd);
+
+ call_thread->control.in_infcall = 1;
+
+ clear_proceed_status (0);
+
+ /* 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;
+
+ disable_watchpoints_before_interactive_call_start ();
+
+ /* We want to print return value, please... */
+ call_thread->control.proceed_to_finish = 1;
+
+ try
+ {
+ proceed (real_pc, GDB_SIGNAL_0);
+
+ /* Inferior function calls are always synchronous, even if the
+ target supports asynchronous execution. */
+ wait_sync_command_done ();
+ }
+ catch (gdb_exception &e)
+ {
+ caught_error = std::move (e);
+ }
+
+ /* If GDB has the prompt blocked before, then ensure that it remains
+ so. normal_stop calls async_enable_stdin, so reset the prompt
+ state again here. In other cases, stdin will be re-enabled by
+ inferior_event_handler, when an exception is thrown. */
+ current_ui->prompt_state = saved_prompt_state;
+ if (current_ui->prompt_state == PROMPT_BLOCKED)
+ delete_file_handler (current_ui->input_fd);
+ else
+ ui_register_input_event_handler (current_ui);
+ current_ui->async = saved_ui_async;
+
+ /* If the infcall does NOT succeed, normal_stop will have already
+ finished the thread states. However, on success, normal_stop
+ defers here, so that we can set back the thread states to what
+ they were before the call. Note that we must also finish the
+ state of new threads that might have spawned while the call was
+ running. The main cases to handle are:
+
+ - "(gdb) print foo ()", or any other command that evaluates an
+ expression at the prompt. (The thread was marked stopped before.)
+
+ - "(gdb) break foo if return_false()" or similar cases where we
+ do an infcall while handling an event (while the thread is still
+ marked running). In this example, whether the condition
+ evaluates true and thus we'll present a user-visible stop is
+ decided elsewhere. */
+ if (!was_running
+ && call_thread_ptid == inferior_ptid
+ && stop_stack_dummy == STOP_STACK_DUMMY)
+ finish_thread_state (user_visible_resume_ptid (0));
+
+ enable_watchpoints_after_interactive_call_stop ();
+
+ /* Call breakpoint_auto_delete on the current contents of the bpstat
+ of inferior call thread.
+ If all error()s out of proceed ended up calling normal_stop
+ (and perhaps they should; it already does in the special case
+ of error out of resume()), then we wouldn't need this. */
+ if (caught_error.reason < 0)
+ {
+ if (call_thread->state != THREAD_EXITED)
+ breakpoint_auto_delete (call_thread->control.stop_bpstat);
+ }
+
+ call_thread->control.in_infcall = saved_in_infcall;
+
+ return caught_error;
+}
+
+/* See infcall.h. */
+
+struct value *
+call_function_by_hand (struct value *function,
+ type *default_return_type,
+ gdb::array_view<value *> args)
+{
+ return call_function_by_hand_dummy (function, default_return_type,
+ args, NULL, NULL);