Select frame when fetching a frame variable in DAP
authorTom Tromey <tromey@adacore.com>
Mon, 21 Aug 2023 19:51:59 +0000 (13:51 -0600)
committerTom Tromey <tromey@adacore.com>
Tue, 5 Sep 2023 17:03:02 +0000 (11:03 -0600)
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".

gdb/python/lib/gdb/dap/next.py
gdb/python/lib/gdb/dap/scopes.py

index 8b112770a0c0971fc1811bba9f695119391b05bc..5046963cb8137384d92964c22b9fdc5f7995a202 100644 (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))
 
 
index 1687094c4ceb27631e9da7e08f8e6d624c0e3154..4874d001216d16043fbc71e7ebdbaeec9e9aad48 100644 (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())