[Lldb-commits] [lldb] [lldb] Still echo the command if we print the error. (PR #171931)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Thu Dec 11 15:59:42 PST 2025
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/171931
>From e36c4076c4ad4a8441cedcb8e00fdca2dbc27e99 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 11 Dec 2025 15:37:31 -0800
Subject: [PATCH 1/2] [lldb] Still echo the command if we print the error.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When the command interpreter is asked to not echo commands but still
print errors, a user has no idea what command caused the error.
For example, when I add `bogus` in my `~/.lldbinit`:
```
$ lldb
error: 'bogus' is not a valid command.
```
Things are even more confusing when we have inline diagnostics, which
point to nothing. For example, when I add `settings set target.run-args
-foo` to my `~/.lldbinit`:
```
❯ lldb
˄˜˜˜
╰─ error: unknown or ambiguous option
```
We should still echo the command if the command fails, making it obvious
which command caused the failure and fixing the inline diagnostics.
Fixes #171514
---
.../source/Interpreter/CommandInterpreter.cpp | 22 +++++++++++++++----
.../Shell/Settings/Inputs/FailedCommand.in | 4 ++++
.../Settings/TestEchoFailedCommands.test | 10 +++++++++
3 files changed, 32 insertions(+), 4 deletions(-)
create mode 100644 lldb/test/Shell/Settings/Inputs/FailedCommand.in
create mode 100644 lldb/test/Shell/Settings/TestEchoFailedCommands.test
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index afc1753e21c46..1e359f9d08ed5 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -3283,6 +3283,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
if (line.empty())
return;
}
+ bool echoed_command = false;
if (!is_interactive) {
// When using a non-interactive file handle (like when sourcing commands
// from a file) we need to echo the command out so we don't just see the
@@ -3291,6 +3292,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
LockedStreamFile locked_stream =
io_handler.GetOutputStreamFileSP()->Lock();
locked_stream.Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
+ echoed_command = true;
}
}
@@ -3310,10 +3312,22 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
lldb_private::CommandReturnObject result(m_debugger.GetUseColor());
HandleCommand(line.c_str(), eLazyBoolCalculate, result);
- // Now emit the command output text from the command we just executed
- if ((result.Succeeded() &&
- io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) ||
- io_handler.GetFlags().Test(eHandleCommandFlagPrintErrors)) {
+ const bool print_result =
+ result.Succeeded() &&
+ io_handler.GetFlags().Test(eHandleCommandFlagPrintResult);
+ const bool print_error =
+ io_handler.GetFlags().Test(eHandleCommandFlagPrintErrors);
+
+ // Now emit the command output text from the command we just executed.
+ if (print_result || print_error) {
+ // If the command failed and we didn't echo it, echo it now so the user
+ // knows which command produced the error.
+ if (!echoed_command && !result.Succeeded() && print_error) {
+ LockedStreamFile locked_stream =
+ io_handler.GetOutputStreamFileSP()->Lock();
+ locked_stream.Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
+ }
+
auto DefaultPrintCallback = [&](const CommandReturnObject &result) {
// Display any inline diagnostics first.
const bool inline_diagnostics = !result.GetImmediateErrorStream() &&
diff --git a/lldb/test/Shell/Settings/Inputs/FailedCommand.in b/lldb/test/Shell/Settings/Inputs/FailedCommand.in
new file mode 100644
index 0000000000000..c3bc5c704fe34
--- /dev/null
+++ b/lldb/test/Shell/Settings/Inputs/FailedCommand.in
@@ -0,0 +1,4 @@
+# This should succeed and not be echoed.
+expr 1+2
+# This should fail and be echoed.
+bogus_command
diff --git a/lldb/test/Shell/Settings/TestEchoFailedCommands.test b/lldb/test/Shell/Settings/TestEchoFailedCommands.test
new file mode 100644
index 0000000000000..3bb465707a41d
--- /dev/null
+++ b/lldb/test/Shell/Settings/TestEchoFailedCommands.test
@@ -0,0 +1,10 @@
+# Test that failed commands are echoed even when echoing is disabled.
+# This ensures users can see which command produced an error.
+
+RUN: mkdir -p %t.home
+RUN: cp %S/Inputs/FailedCommand.in %t.home/.lldbinit
+RUN: env HOME=%t.home %lldb-init -b 2>&1 | FileCheck %s
+
+CHECK-NOT: expr 1+2
+CHECK: (lldb) bogus_command
+CHECK: error: 'bogus_command' is not a valid command
>From fe39fd3cb16230b0ccf889caa32c88acce7b426f Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 11 Dec 2025 15:59:27 -0800
Subject: [PATCH 2/2] Implement Adrian's suggestion
---
lldb/source/Interpreter/CommandInterpreter.cpp | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 1e359f9d08ed5..5e608f8caf42a 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -3289,9 +3289,8 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
// from a file) we need to echo the command out so we don't just see the
// command output and no command...
if (EchoCommandNonInteractive(line, io_handler.GetFlags())) {
- LockedStreamFile locked_stream =
- io_handler.GetOutputStreamFileSP()->Lock();
- locked_stream.Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
+ io_handler.GetOutputStreamFileSP()->Lock()
+ << io_handler.GetPrompt() << line << '\n';
echoed_command = true;
}
}
@@ -3323,9 +3322,8 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
// If the command failed and we didn't echo it, echo it now so the user
// knows which command produced the error.
if (!echoed_command && !result.Succeeded() && print_error) {
- LockedStreamFile locked_stream =
- io_handler.GetOutputStreamFileSP()->Lock();
- locked_stream.Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
+ io_handler.GetOutputStreamFileSP()->Lock()
+ << io_handler.GetPrompt() << line << '\n';
}
auto DefaultPrintCallback = [&](const CommandReturnObject &result) {
More information about the lldb-commits
mailing list