https://github.com/DrSergei updated 
https://github.com/llvm/llvm-project/pull/215228

>From 6d1c6459ea0da00ea7073b455959f012b8510061 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <[email protected]>
Date: Mon, 10 Aug 2026 12:17:03 +0300
Subject: [PATCH 1/3] [lldb-dap] Preserve watchpoints from console

---
 .../TestDAP_setDataBreakpoints.py             | 41 +++++++++++++++++++
 lldb/tools/lldb-dap/DAP.h                     |  1 +
 .../SetDataBreakpointsRequestHandler.cpp      |  8 +++-
 lldb/tools/lldb-dap/Watchpoint.h              |  2 +
 4 files changed, 51 insertions(+), 1 deletion(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index 225a947674351..bad48b0ffbf0f 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -182,6 +182,47 @@ def test_functionality(self):
         stop_event = 
session.continue_to_breakpoint(self.expect_not_none(bp_cond.id))
         self.assertEqual(session.top_frame_from(stop_event).locals["x"].value, 
"10")
 
+    @skipIfWindows
+    def test_console_watchpoint_preserved(self):
+        """Test setDataBreakpoints must not delete watchpoints created via the 
console."""
+        source = "main.cpp"
+        program = self.getBuildArtifact("a.out")
+        session = self.build_and_create_session()
+        first_loop_break_line = line_number(source, "// first loop breakpoint")
+        with session.configure(LaunchArgs(program)) as ctx:
+            session.resolve_source_breakpoints(source, [first_loop_break_line])
+        stop_event = 
session.verify_stopped_on_breakpoint(after=ctx.process_event)
+        top_frame = session.top_frame_from(stop_event)
+
+        # Create a watchpoint via the LLDB console.
+        resp_body = session.evaluate("`watchpoint set variable x", 
context="repl")
+        session.verify_evaluate(resp_body, matches=r".*Watchpoint created.*")
+        resp_body = session.evaluate("`watchpoint list", context="repl")
+        session.verify_evaluate(resp_body, matches=r".*Watchpoint 1:.*")
+
+        # Set a data breakpoint via DAP.
+        arr = top_frame.locals["arr"]
+        arr_var_ref = self.expect_not_none(arr.variablesReference)
+        response_arr_2 = session.data_breakpoint_info(
+            "[2]", arr_var_ref, top_frame.frame.id
+        )
+        arr_2_data_id = self.expect_not_none(response_arr_2.body.dataId)
+        set_response = session.set_data_breakpoints(
+            [DataBreakpoint(dataId=arr_2_data_id, accessType="write")]
+        )
+        [bp_arr_2] = set_response.body.breakpoints
+        self.assertTrue(bp_arr_2.verified)
+
+        resp_body = session.evaluate("`watchpoint list", context="repl")
+        session.verify_evaluate(resp_body, matches=r".*Watchpoint 1:.*")
+
+        session.set_data_breakpoints([])
+        resp_body = session.evaluate("`watchpoint list", context="repl")
+        session.verify_evaluate(resp_body, matches=r".*Watchpoint 1:.*")
+
+        session.evaluate("`watchpoint delete 1", context="repl")
+        session.continue_to_exit()
+
     @skipIfWindows
     def test_bytes(self):
         """Tests setting data breakpoints on memory range."""
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 3e2b1d4782147..c09b149ae3f53 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -107,6 +107,7 @@ struct DAP final : public DAPTransport::MessageHandler {
   FunctionBreakpointMap function_breakpoints;
   InstructionBreakpointMap instruction_breakpoints;
   std::vector<ExceptionBreakpoint> exception_breakpoints;
+  std::vector<lldb::watch_id_t> data_breakpoints;
 
   /// Map step in target id to list of function targets that user can choose.
   llvm::DenseMap<lldb::addr_t, std::string> step_in_targets;
diff --git a/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
index 1caaa23bf06f6..0540dfcd9d255 100644
--- a/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
@@ -25,7 +25,10 @@ SetDataBreakpointsRequestHandler::Run(
     const protocol::SetDataBreakpointsArguments &args) const {
   std::vector<protocol::Breakpoint> response_breakpoints;
 
-  dap.target.DeleteAllWatchpoints();
+  for (lldb::watch_id_t watch_id : dap.data_breakpoints)
+    dap.target.DeleteWatchpoint(watch_id);
+  dap.data_breakpoints.clear();
+
   std::vector<Watchpoint> watchpoints;
   for (const auto &bp : args.breakpoints)
     watchpoints.emplace_back(dap, bp);
@@ -38,6 +41,9 @@ SetDataBreakpointsRequestHandler::Run(
     if (addresses.count(iter->GetAddress()) == 0) {
       iter->SetWatchpoint();
       addresses.insert(iter->GetAddress());
+      if (lldb::watch_id_t watch_id = iter->GetID();
+          watch_id != LLDB_INVALID_WATCH_ID)
+        dap.data_breakpoints.push_back(watch_id);
     }
   }
   for (auto wp : watchpoints)
diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h
index d943e1218bdcd..f73b89e674329 100644
--- a/lldb/tools/lldb-dap/Watchpoint.h
+++ b/lldb/tools/lldb-dap/Watchpoint.h
@@ -34,6 +34,8 @@ class Watchpoint : public BreakpointBase {
 
   lldb::addr_t GetAddress() const { return m_addr; }
 
+  lldb::watch_id_t GetID() { return m_wp.GetID(); }
+
 protected:
   lldb::addr_t m_addr;
   size_t m_size;

>From 9f479360cf0993483cc44cbfe6d48621c7c8c16c Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <[email protected]>
Date: Wed, 12 Aug 2026 18:32:13 +0300
Subject: [PATCH 2/3] Fix review comments

---
 .../lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py   | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index bad48b0ffbf0f..a3cf2bbb5b360 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -5,7 +5,7 @@
 from lldbsuite.test.decorators import skipIfWasm, skipIfWindows
 from lldbsuite.test.lldbtest import line_number
 from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
-from lldbsuite.test.tools.lldb_dap.types import DataBreakpoint, LaunchArgs
+from lldbsuite.test.tools.lldb_dap.types import DataBreakpoint, LaunchArgs, 
StoppedReason
 
 
 @skipIfWasm  # data breakpoints map to watchpoints.
@@ -220,6 +220,10 @@ def test_console_watchpoint_preserved(self):
         resp_body = session.evaluate("`watchpoint list", context="repl")
         session.verify_evaluate(resp_body, matches=r".*Watchpoint 1:.*")
 
+        # Verify watchpoint from console.
+        stop_event = 
session.continue_to_next_stop(exp_reason=StoppedReason.DATA_BREAKPOINT)
+        self.assertEqual(session.top_frame_from(stop_event).locals["x"].value, 
"2")
+
         session.evaluate("`watchpoint delete 1", context="repl")
         session.continue_to_exit()
 

>From 196d22d178ff8fe31146171948ee3975560c87b3 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov <[email protected]>
Date: Wed, 12 Aug 2026 18:48:29 +0300
Subject: [PATCH 3/3] Fix formatting

---
 .../lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py     | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index a3cf2bbb5b360..0383daf290a5a 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -221,7 +221,9 @@ def test_console_watchpoint_preserved(self):
         session.verify_evaluate(resp_body, matches=r".*Watchpoint 1:.*")
 
         # Verify watchpoint from console.
-        stop_event = 
session.continue_to_next_stop(exp_reason=StoppedReason.DATA_BREAKPOINT)
+        stop_event = session.continue_to_next_stop(
+            exp_reason=StoppedReason.DATA_BREAKPOINT
+        )
         self.assertEqual(session.top_frame_from(stop_event).locals["x"].value, 
"2")
 
         session.evaluate("`watchpoint delete 1", context="repl")

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to