[Lldb-commits] [lldb] fff8f39 - [lldb-dap] Fix logpoint to breakpoint conversion (#222906)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 14 02:18:17 PDT 2026
Author: Sergei Druzhkov
Date: 2026-09-14T12:18:12+03:00
New Revision: fff8f393a9aa7c6199a3efa4e2d8f439f8c0f06e
URL: https://github.com/llvm/llvm-project/commit/fff8f393a9aa7c6199a3efa4e2d8f439f8c0f06e
DIFF: https://github.com/llvm/llvm-project/commit/fff8f393a9aa7c6199a3efa4e2d8f439f8c0f06e.diff
LOG: [lldb-dap] Fix logpoint to breakpoint conversion (#222906)
When user sets logpoint and after that removes `logMessage`, which
implicitly converts it to usual breakpoint, breakpoint still has
`BreakpointHitCallback`, which leads to missed stops.
Added:
Modified:
lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py
lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
lldb/tools/lldb-dap/SourceBreakpoint.cpp
lldb/unittests/DAP/ProtocolTypesTest.cpp
Removed:
################################################################################
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py
index 635387f593cf7..4d968286880db 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py
@@ -78,6 +78,61 @@ def test_logMessage_basic(self):
)
session.continue_to_exit()
+ @skipIfWindows
+ def test_logmessage_claeared(self):
+ """Tests removing logMessage restores a stopping breakpoint."""
+ session = self.build_and_create_session()
+ initial_stop = self.stop_at_before_loop_line(session)
+ loop_line = line_number("main.cpp", "// break loop")
+ after_loop_line = line_number("main.cpp", "// after loop")
+ log_prefix = "This is log message for "
+
+ [logpoint_id, post_loop_breakpoint_id] = session.resolve_source_breakpoints(
+ self.main_path,
+ [
+ SourceBreakpoint(loop_line, logMessage=log_prefix + "{i}"),
+ SourceBreakpoint(after_loop_line),
+ ],
+ )
+
+ # Change logpoint to usual breakpoint and check that id preserved.
+ [breakpoint_id, _] = session.resolve_source_breakpoints(
+ self.main_path,
+ [
+ SourceBreakpoint(loop_line, logMessage=None),
+ SourceBreakpoint(after_loop_line),
+ ],
+ )
+ self.assertEqual(breakpoint_id, logpoint_id)
+
+ # Check that stop works as expected for updated logpoint.
+ loop_stop = session.continue_to_breakpoint(breakpoint_id)
+ frame = session.top_frame_from(loop_stop)
+ self.assertEqual(frame.locals["i"].value_as_int, 0)
+ captured = session.collect_console(after=initial_stop, until=loop_stop)
+ self.assertNotIn(log_prefix, captured.seen_texts)
+
+ # Change breakpoint to logpoint back.
+ [restored_id, _] = session.resolve_source_breakpoints(
+ self.main_path,
+ [
+ SourceBreakpoint(loop_line, logMessage=log_prefix + "{i}"),
+ SourceBreakpoint(after_loop_line),
+ ],
+ )
+ self.assertEqual(restored_id, logpoint_id)
+
+ # Check that logpoint prints messages.
+ post_loop_stop = session.continue_to_breakpoint(post_loop_breakpoint_id)
+ captured = session.collect_console(after=loop_stop, until=post_loop_stop)
+ messages = [
+ line
+ for line in captured.seen_texts.splitlines()
+ if line.startswith(log_prefix)
+ ]
+ self.assertEqual(messages, [log_prefix + str(i) for i in range(1, 10)])
+ session.continue_to_exit()
+
@skipIfWindows
def test_logmessage_advanced(self):
"""Tests breakpoint logmessage functionality for complex expression."""
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 929e0765c197f..b30fe191373ce 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -871,8 +871,8 @@ llvm::json::Value toJSON(const SourceBreakpoint &SB) {
result.insert({"condition", *SB.condition});
if (SB.hitCondition)
result.insert({"hitCondition", *SB.hitCondition});
- if (SB.logMessage)
- result.insert({"logMessage", *SB.logMessage});
+ if (!SB.logMessage.empty())
+ result.insert({"logMessage", SB.logMessage});
if (SB.mode)
result.insert({"mode", *SB.mode});
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 4274a0513f6ee..a243d2438c4f4 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -689,7 +689,7 @@ struct SourceBreakpoint {
/// capability `supportsLogPoints` is true.
/// If either `hitCondition` or `condition` is specified, then the message
/// should only be logged if those conditions are met.
- std::optional<String> logMessage;
+ String logMessage;
/// The mode of this breakpoint. If defined, this must be one of the
/// `breakpointModes` the debug adapter advertised in its `Capabilities`.
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index fbc995e8a6e3f..82a07f1f99552 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -33,8 +33,7 @@ namespace lldb_dap {
SourceBreakpoint::SourceBreakpoint(DAP &dap,
const protocol::SourceBreakpoint &breakpoint)
: Breakpoint(dap, breakpoint.condition, breakpoint.hitCondition),
- m_log_message(breakpoint.logMessage.value_or("")),
- m_line(breakpoint.line),
+ m_log_message(breakpoint.logMessage), m_line(breakpoint.line),
m_column(breakpoint.column.value_or(LLDB_INVALID_COLUMN_NUMBER)) {}
llvm::Error SourceBreakpoint::SetBreakpoint(const protocol::Source &source) {
@@ -281,6 +280,11 @@ lldb::SBError SourceBreakpoint::FormatLogText(llvm::StringRef text,
void SourceBreakpoint::SetLogMessage() {
m_log_message_parts.clear();
+ if (m_log_message.empty()) {
+ m_bp.SetCallback(nullptr, nullptr);
+ return;
+ }
+
// Contains unmatched open curly braces indices.
std::vector<int> unmatched_curly_braces;
diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp b/lldb/unittests/DAP/ProtocolTypesTest.cpp
index 54a94fb842d45..596bbb8a7ca73 100644
--- a/lldb/unittests/DAP/ProtocolTypesTest.cpp
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -163,6 +163,20 @@ TEST(ProtocolTypesTest, SourceBreakpoint) {
EXPECT_EQ(source_breakpoint.mode, deserialized_source_breakpoint->mode);
}
+TEST(ProtocolTypesTest, SourceBreakpointOptionalLogMessage) {
+ for (StringRef json :
+ {R"({"line": 0})", R"({"line": 0, "logMessage": ""})"}) {
+ Expected<SourceBreakpoint> source_breakpoint =
+ parse<SourceBreakpoint>(json);
+ ASSERT_THAT_EXPECTED(source_breakpoint, Succeeded());
+ EXPECT_EQ(source_breakpoint->line, 0u);
+ EXPECT_TRUE(source_breakpoint->logMessage.empty());
+ }
+
+ EXPECT_THAT_EXPECTED(
+ parse<SourceBreakpoint>(R"({"line": 0, "logMessage": null})"), Failed());
+}
+
TEST(ProtocolTypesTest, FunctionBreakpoint) {
FunctionBreakpoint function_breakpoint;
function_breakpoint.name = "myFunction";
More information about the lldb-commits
mailing list