Select frame when fetching a frame variable in DAP

Right now, if a program uses multiple languages, DAP value formatting
will always use the language of the innermost frame.  However, it is
better to use the variable's defining frame instead.  This patch does
this by selecting the frame first.

This also fixes a possibly latent bug in the "stepOut" command --
"finish" is sensitive to the selected frame, but the DAP code may
already select other frames when convenient.  The DAP stepOut request
only works on the newest frame, so be sure to select it before
invoking "finish".
This commit is contained in:
Tom Tromey
2023-08-21 13:51:59 -06:00
parent 84914f598e
commit 91c7233d2d
2 changed files with 12 additions and 3 deletions
+8 -3
View File
@@ -23,9 +23,10 @@ from .state import set_thread
# Helper function to set the current thread and the scheduler-locking
# mode. Returns True if scheduler-locking was successfully set to
# 'on', False in all other cases, including error.
# 'on', False in all other cases, including error. When SELECT is
# True, also select that thread's newest frame.
@in_gdb_thread
def _handle_thread_step(thread_id, single_thread):
def _handle_thread_step(thread_id, single_thread, select=False):
# Ensure we're going to step the correct thread.
set_thread(thread_id)
if single_thread:
@@ -41,6 +42,10 @@ def _handle_thread_step(thread_id, single_thread):
gdb.execute("set scheduler-locking " + arg, from_tty=True, to_string=True)
except gdb.error:
result = False
# Other DAP code may select a frame, and the "finish" command uses
# the selected frame.
if select:
gdb.newest_frame().select()
return result
@@ -70,7 +75,7 @@ def step_in(
@request("stepOut")
def step_out(*, threadId: int, singleThread: bool = False):
send_gdb(lambda: _handle_thread_step(threadId, singleThread))
send_gdb(lambda: _handle_thread_step(threadId, singleThread, True))
send_gdb(ExecutionInvoker("finish", StopKinds.STEP))
+4
View File
@@ -49,6 +49,10 @@ class _ScopeReference(BaseReference):
@in_gdb_thread
def fetch_one_child(self, idx):
# Make sure to select the frame first. Ideally this would not
# be needed, but this is a way to set the current language
# properly so that language-dependent APIs will work.
self.inf_frame.select()
# Here SYM will conform to the SymValueWrapper interface.
sym = self.var_list[idx]
name = str(sym.symbol())