[Lldb-commits] [lldb] [lldb] Store the command in the CommandReturnObject (PR #125132)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Thu Jan 30 15:19:12 PST 2025
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/125132
None
>From 24ddc550e3ee61b863cbaea05ff49981bc20f7ad Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 30 Jan 2025 14:25:16 -0800
Subject: [PATCH 1/4] [lldb] Use llvm::Error instead of CommandReturnObject for
error reporting
Use `llvm::Error` instead of `CommandReturnObject` for error reporting.
The command return objects were populated with errors but never
displayed. With this patch they're at least logged.
---
lldb/include/lldb/Interpreter/Options.h | 4 +-
lldb/source/Interpreter/CommandAlias.cpp | 49 +++++------
lldb/source/Interpreter/CommandObject.cpp | 2 +-
lldb/source/Interpreter/Options.cpp | 87 ++++++++++---------
.../DarwinLog/StructuredDataDarwinLog.cpp | 9 +-
5 files changed, 77 insertions(+), 74 deletions(-)
diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h
index 9a6a17c2793fa4..864bda6f24c8cc 100644
--- a/lldb/include/lldb/Interpreter/Options.h
+++ b/lldb/include/lldb/Interpreter/Options.h
@@ -76,12 +76,12 @@ class Options {
// This gets passed the short option as an integer...
void OptionSeen(int short_option);
- bool VerifyOptions(CommandReturnObject &result);
+ llvm::Error VerifyOptions();
// Verify that the options given are in the options table and can be used
// together, but there may be some required options that are missing (used to
// verify options that get folded into command aliases).
- bool VerifyPartialOptions(CommandReturnObject &result);
+ llvm::Error VerifyPartialOptions();
void OutputFormattedUsageText(Stream &strm,
const OptionDefinition &option_def,
diff --git a/lldb/source/Interpreter/CommandAlias.cpp b/lldb/source/Interpreter/CommandAlias.cpp
index c5971b52f837fa..ac0c7a3279e64b 100644
--- a/lldb/source/Interpreter/CommandAlias.cpp
+++ b/lldb/source/Interpreter/CommandAlias.cpp
@@ -10,6 +10,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatAdapters.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
@@ -20,20 +21,17 @@
using namespace lldb;
using namespace lldb_private;
-static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
+static llvm::Error
+ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
llvm::StringRef options_args,
OptionArgVectorSP &option_arg_vector_sp) {
- bool success = true;
OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
if (options_args.size() < 1)
- return true;
+ return llvm::Error::success();
Args args(options_args);
std::string options_string(options_args);
- // TODO: Find a way to propagate errors in this CommandReturnObject up the
- // stack.
- CommandReturnObject result(false);
// Check to see if the command being aliased can take any command options.
Options *options = cmd_obj_sp->GetOptions();
if (options) {
@@ -45,34 +43,30 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
llvm::Expected<Args> args_or =
options->ParseAlias(args, option_arg_vector, options_string);
- if (!args_or) {
- result.AppendError(toString(args_or.takeError()));
- result.AppendError("Unable to create requested alias.\n");
- return false;
- }
+ if (!args_or)
+ return llvm::createStringError(
+ llvm::formatv("unable to create alias: {0}",
+ llvm::fmt_consume(args_or.takeError())));
args = std::move(*args_or);
- options->VerifyPartialOptions(result);
- if (!result.Succeeded() &&
- result.GetStatus() != lldb::eReturnStatusStarted) {
- result.AppendError("Unable to create requested alias.\n");
- return false;
- }
+ if (llvm::Error error = options->VerifyPartialOptions())
+ return error;
}
if (!options_string.empty()) {
- if (cmd_obj_sp->WantsRawCommandString())
- option_arg_vector->emplace_back(CommandInterpreter::g_argument,
- -1, options_string);
- else {
+ if (cmd_obj_sp->WantsRawCommandString()) {
+ option_arg_vector->emplace_back(CommandInterpreter::g_argument, -1,
+ options_string);
+ } else {
for (auto &entry : args.entries()) {
if (!entry.ref().empty())
- option_arg_vector->emplace_back(std::string(CommandInterpreter::g_argument), -1,
+ option_arg_vector->emplace_back(
+ std::string(CommandInterpreter::g_argument), -1,
std::string(entry.ref()));
}
}
}
- return success;
+ return llvm::Error::success();
}
CommandAlias::CommandAlias(CommandInterpreter &interpreter,
@@ -85,10 +79,15 @@ CommandAlias::CommandAlias(CommandInterpreter &interpreter,
m_option_args_sp(new OptionArgVector),
m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
m_did_set_help_long(false) {
- if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
+ if (llvm::Error error =
+ ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
+ // FIXME: Find a way to percolate this error up.
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(error),
+ "ProcessAliasOptionsArgs failed: {0}");
+ } else {
m_underlying_command_sp = cmd_sp;
for (int i = 0;
- auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
+ auto *cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
i++) {
m_arguments.push_back(*cmd_entry);
}
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 559e2e7a76dd99..4f21c75c2c136a 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -124,7 +124,7 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
error = Status::FromError(args_or.takeError());
if (error.Success()) {
- if (options->VerifyOptions(result))
+ if (options->VerifyOptions())
return true;
} else {
result.SetError(error.takeError());
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 893a3b71604ba8..fdadba62987d36 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -138,46 +138,6 @@ void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
}
}
-bool Options::VerifyOptions(CommandReturnObject &result) {
- bool options_are_valid = false;
-
- int num_levels = GetRequiredOptions().size();
- if (num_levels) {
- for (int i = 0; i < num_levels && !options_are_valid; ++i) {
- // This is the correct set of options if: 1). m_seen_options contains
- // all of m_required_options[i] (i.e. all the required options at this
- // level are a subset of m_seen_options); AND 2). { m_seen_options -
- // m_required_options[i] is a subset of m_options_options[i] (i.e. all
- // the rest of m_seen_options are in the set of optional options at this
- // level.
-
- // Check to see if all of m_required_options[i] are a subset of
- // m_seen_options
- if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
- // Construct the set difference: remaining_options = {m_seen_options} -
- // {m_required_options[i]}
- OptionSet remaining_options;
- OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
- remaining_options);
- // Check to see if remaining_options is a subset of
- // m_optional_options[i]
- if (IsASubset(remaining_options, GetOptionalOptions()[i]))
- options_are_valid = true;
- }
- }
- } else {
- options_are_valid = true;
- }
-
- if (options_are_valid) {
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- } else {
- result.AppendError("invalid combination of options for the given command");
- }
-
- return options_are_valid;
-}
-
// This is called in the Options constructor, though we could call it lazily if
// that ends up being a performance problem.
@@ -590,13 +550,50 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject &cmd,
strm.SetIndentLevel(save_indent_level);
}
+llvm::Error Options::VerifyOptions() {
+ bool options_are_valid = false;
+
+ int num_levels = GetRequiredOptions().size();
+ if (num_levels) {
+ for (int i = 0; i < num_levels && !options_are_valid; ++i) {
+ // This is the correct set of options if: 1). m_seen_options contains
+ // all of m_required_options[i] (i.e. all the required options at this
+ // level are a subset of m_seen_options); AND 2). { m_seen_options -
+ // m_required_options[i] is a subset of m_options_options[i] (i.e. all
+ // the rest of m_seen_options are in the set of optional options at this
+ // level.
+
+ // Check to see if all of m_required_options[i] are a subset of
+ // m_seen_options
+ if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
+ // Construct the set difference: remaining_options = {m_seen_options} -
+ // {m_required_options[i]}
+ OptionSet remaining_options;
+ OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
+ remaining_options);
+ // Check to see if remaining_options is a subset of
+ // m_optional_options[i]
+ if (IsASubset(remaining_options, GetOptionalOptions()[i]))
+ options_are_valid = true;
+ }
+ }
+ } else {
+ options_are_valid = true;
+ }
+
+ if (!options_are_valid)
+ return llvm::createStringError(
+ "invalid combination of options for the given command");
+
+ return llvm::Error::success();
+}
+
// This function is called when we have been given a potentially incomplete set
// of options, such as when an alias has been defined (more options might be
// added at at the time the alias is invoked). We need to verify that the
// options in the set m_seen_options are all part of a set that may be used
// together, but m_seen_options may be missing some of the "required" options.
-
-bool Options::VerifyPartialOptions(CommandReturnObject &result) {
+llvm::Error Options::VerifyPartialOptions() {
bool options_are_valid = false;
int num_levels = GetRequiredOptions().size();
@@ -613,7 +610,11 @@ bool Options::VerifyPartialOptions(CommandReturnObject &result) {
}
}
- return options_are_valid;
+ if (!options_are_valid)
+ return llvm::createStringError(
+ "invalid combination of options for the given command");
+
+ return llvm::Error::success();
}
bool Options::HandleOptionCompletion(CompletionRequest &request,
diff --git a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index 4ca8bd2f9085df..82f18c5fe37a21 100644
--- a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -975,8 +975,6 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
EnableOptionsSP options_sp(new EnableOptions());
options_sp->NotifyOptionParsingStarting(&exe_ctx);
- CommandReturnObject result(debugger.GetUseColor());
-
// Parse the arguments.
auto options_property_sp =
debugger.GetPropertyValue(nullptr,
@@ -1013,8 +1011,13 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
return EnableOptionsSP();
}
- if (!options_sp->VerifyOptions(result))
+ if (llvm::Error error = options_sp->VerifyOptions()) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "Parsing plugin.structured-data.darwin-log.auto-enable-options value "
+ "failed: {0}");
return EnableOptionsSP();
+ }
// We successfully parsed and validated the options.
return options_sp;
>From 29ebafd86dcbb8a22542cab3abc40174e021f65d Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 30 Jan 2025 14:33:58 -0800
Subject: [PATCH 2/4] Fix formatting
---
lldb/source/Interpreter/CommandAlias.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lldb/source/Interpreter/CommandAlias.cpp b/lldb/source/Interpreter/CommandAlias.cpp
index ac0c7a3279e64b..b45fcca358a5ee 100644
--- a/lldb/source/Interpreter/CommandAlias.cpp
+++ b/lldb/source/Interpreter/CommandAlias.cpp
@@ -23,8 +23,8 @@ using namespace lldb_private;
static llvm::Error
ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
- llvm::StringRef options_args,
- OptionArgVectorSP &option_arg_vector_sp) {
+ llvm::StringRef options_args,
+ OptionArgVectorSP &option_arg_vector_sp) {
OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
if (options_args.size() < 1)
@@ -61,7 +61,7 @@ ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
if (!entry.ref().empty())
option_arg_vector->emplace_back(
std::string(CommandInterpreter::g_argument), -1,
- std::string(entry.ref()));
+ std::string(entry.ref()));
}
}
}
>From 5ede4321a6e901f7fe7d42ccd59cb470b84715c5 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 30 Jan 2025 14:42:04 -0800
Subject: [PATCH 3/4] Fix boolean inversion
---
lldb/source/Interpreter/CommandObject.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 4f21c75c2c136a..9ffa5a8ba71188 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -124,11 +124,14 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
error = Status::FromError(args_or.takeError());
if (error.Success()) {
- if (options->VerifyOptions())
- return true;
- } else {
- result.SetError(error.takeError());
+ if (llvm::Error error = options->VerifyOptions()) {
+ result.SetError(std::move(error));
+ return false;
+ }
+ return true;
}
+
+ result.SetError(error.takeError());
result.SetStatus(eReturnStatusFailed);
return false;
}
>From 014ba7b2503ec86393c1d9e8c4dc82f5c2193d43 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 30 Jan 2025 15:00:14 -0800
Subject: [PATCH 4/4] [lldb] Store the command in the CommandReturnObject
---
lldb/include/lldb/API/SBCommandReturnObject.h | 2 ++
.../lldb/Interpreter/CommandReturnObject.h | 8 +++++++-
lldb/source/API/SBCommandReturnObject.cpp | 9 ++++++++-
lldb/source/Breakpoint/BreakpointOptions.cpp | 3 ++-
.../source/Commands/CommandObjectExpression.cpp | 2 +-
.../Commands/CommandObjectWatchpointCommand.cpp | 3 ++-
lldb/source/Core/Debugger.cpp | 2 +-
lldb/source/Expression/REPL.cpp | 2 +-
lldb/source/Interpreter/CommandInterpreter.cpp | 9 ++++++---
lldb/source/Interpreter/CommandReturnObject.cpp | 5 +++--
.../DarwinLog/StructuredDataDarwinLog.cpp | 3 ++-
lldb/source/Target/Target.cpp | 2 +-
.../TestSBCommandReturnObject.py | 17 +++++++++++++++++
lldb/tools/lldb-test/lldb-test.cpp | 6 +++---
14 files changed, 56 insertions(+), 17 deletions(-)
create mode 100644 lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py
diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h
index e8e20a3f3016b8..4096c5bafdcfc9 100644
--- a/lldb/include/lldb/API/SBCommandReturnObject.h
+++ b/lldb/include/lldb/API/SBCommandReturnObject.h
@@ -42,6 +42,8 @@ class LLDB_API SBCommandReturnObject {
bool IsValid() const;
+ const char *GetCommand();
+
const char *GetOutput();
const char *GetError();
diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h
index f96da34889a324..f588032c8acab0 100644
--- a/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -27,10 +27,14 @@ namespace lldb_private {
class CommandReturnObject {
public:
- CommandReturnObject(bool colors);
+ CommandReturnObject(std::string command, bool colors);
~CommandReturnObject() = default;
+ const std::string &GetCommand() const { return m_command; }
+
+ void SetCommand(std::string command) { m_command = std::move(command); }
+
/// Format any inline diagnostics with an indentation of \c indent.
std::string GetInlineDiagnosticString(unsigned indent) const;
@@ -182,6 +186,8 @@ class CommandReturnObject {
private:
enum { eStreamStringIndex = 0, eImmediateStreamIndex = 1 };
+ std::string m_command;
+
StreamTee m_out_stream;
StreamTee m_err_stream;
std::vector<DiagnosticDetail> m_diagnostics;
diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp
index 9df8aa48b99366..07355f9318e8dc 100644
--- a/lldb/source/API/SBCommandReturnObject.cpp
+++ b/lldb/source/API/SBCommandReturnObject.cpp
@@ -23,7 +23,7 @@ using namespace lldb_private;
class lldb_private::SBCommandReturnObjectImpl {
public:
- SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {}
+ SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject("", false)) {}
SBCommandReturnObjectImpl(CommandReturnObject &ref)
: m_ptr(&ref), m_owned(false) {}
SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs)
@@ -84,6 +84,13 @@ SBCommandReturnObject::operator bool() const {
return true;
}
+const char *SBCommandReturnObject::GetCommand() {
+ LLDB_INSTRUMENT_VA(this);
+
+ ConstString output(ref().GetCommand());
+ return output.AsCString(/*value_if_empty*/ "");
+}
+
const char *SBCommandReturnObject::GetOutput() {
LLDB_INSTRUMENT_VA(this);
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 09abcf5e081d28..e825ca7b6d7d1e 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -616,7 +616,8 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction(
Target *target = exe_ctx.GetTargetPtr();
if (target) {
Debugger &debugger = target->GetDebugger();
- CommandReturnObject result(debugger.GetUseColor());
+ CommandReturnObject result("<breakpoint callback>",
+ debugger.GetUseColor());
// Rig up the results secondary output stream to the debugger's, so the
// output will come out synchronously if the debugger is set up that way.
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 13491b5c794425..84ec1f37cdf9e8 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -504,7 +504,7 @@ void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
CommandReturnObject return_obj(
- GetCommandInterpreter().GetDebugger().GetUseColor());
+ line, GetCommandInterpreter().GetDebugger().GetUseColor());
EvaluateExpression(line.c_str(), *output_sp, *error_sp, return_obj);
if (output_sp)
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index ab1a2b390936c4..d9b1dc8f5d51f5 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -243,7 +243,8 @@ are no syntax errors may indicate that a function was declared but never called.
Target *target = exe_ctx.GetTargetPtr();
if (target) {
Debugger &debugger = target->GetDebugger();
- CommandReturnObject result(debugger.GetUseColor());
+ CommandReturnObject result("<watchpoint callback>",
+ debugger.GetUseColor());
// Rig up the results secondary output stream to the debugger's, so the
// output will come out synchronously if the debugger is set up that
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 2df2aeb20aa26a..9c62600994c3a5 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -799,7 +799,7 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) {
CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter();
if (cmd_interpreter.GetSaveSessionOnQuit()) {
- CommandReturnObject result(debugger_sp->GetUseColor());
+ CommandReturnObject result("<save transcript>", debugger_sp->GetUseColor());
cmd_interpreter.SaveTranscript(result);
if (result.Succeeded())
(*debugger_sp->GetAsyncOutputStream())
diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp
index 4b53537e50e62a..75a16a1ef2ce42 100644
--- a/lldb/source/Expression/REPL.cpp
+++ b/lldb/source/Expression/REPL.cpp
@@ -255,7 +255,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
ci.SetPromptOnQuit(false);
// Execute the command
- CommandReturnObject result(debugger.GetUseColor());
+ CommandReturnObject result(code, debugger.GetUseColor());
result.SetImmediateOutputStream(output_sp);
result.SetImmediateErrorStream(error_sp);
ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 4869b811f99e71..422fe03efa8224 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -1893,6 +1893,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
LLDB_LOGF(log, "Processing command: %s", command_line);
LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
+ result.SetCommand(command_line);
+
if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) {
result.AppendError("... Interrupted");
return false;
@@ -2616,7 +2618,7 @@ void CommandInterpreter::HandleCommands(
m_debugger.GetPrompt().str().c_str(), cmd);
}
- CommandReturnObject tmp_result(m_debugger.GetUseColor());
+ CommandReturnObject tmp_result(cmd, m_debugger.GetUseColor());
tmp_result.SetInteractive(result.GetInteractive());
tmp_result.SetSuppressImmediateOutput(true);
@@ -2644,7 +2646,8 @@ void CommandInterpreter::HandleCommands(
(uint64_t)idx, cmd, error_msg);
m_debugger.SetAsyncExecution(old_async_execution);
return;
- } else if (options.GetPrintResults()) {
+ }
+ if (options.GetPrintResults()) {
result.AppendMessageWithFormatv("Command #{0} '{1}' failed with {2}",
(uint64_t)idx + 1, cmd, error_msg);
}
@@ -3177,7 +3180,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
RestoreExecutionContext();
});
- lldb_private::CommandReturnObject result(m_debugger.GetUseColor());
+ lldb_private::CommandReturnObject result(line, m_debugger.GetUseColor());
HandleCommand(line.c_str(), eLazyBoolCalculate, result);
// Now emit the command output text from the command we just executed
diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp
index 0a2948e8e6ca44..85bbbda8fda971 100644
--- a/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -47,8 +47,9 @@ static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s) {
strm.EOL();
}
-CommandReturnObject::CommandReturnObject(bool colors)
- : m_out_stream(colors), m_err_stream(colors), m_colors(colors) {}
+CommandReturnObject::CommandReturnObject(std::string command, bool colors)
+ : m_command(std::move(command)), m_out_stream(colors), m_err_stream(colors),
+ m_colors(colors) {}
void CommandReturnObject::AppendErrorWithFormat(const char *format, ...) {
SetStatus(eReturnStatusFailed);
diff --git a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index 82f18c5fe37a21..81f5444a49b997 100644
--- a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -1034,7 +1034,8 @@ bool RunEnableCommand(CommandInterpreter &interpreter) {
}
// Run the command.
- CommandReturnObject return_object(interpreter.GetDebugger().GetUseColor());
+ CommandReturnObject return_object("<enable command>",
+ interpreter.GetDebugger().GetUseColor());
interpreter.HandleCommand(command_stream.GetData(), eLazyBoolNo,
return_object);
return return_object.Succeeded();
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 8d77097477651c..b5c2db606e355c 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3933,7 +3933,7 @@ Target::StopHookCommandLine::HandleStop(ExecutionContext &exc_ctx,
if (!m_commands.GetSize())
return StopHookResult::KeepStopped;
- CommandReturnObject result(false);
+ CommandReturnObject result("<stop hook>", false);
result.SetImmediateOutputStream(output_sp);
result.SetInteractive(false);
Debugger &debugger = exc_ctx.GetTargetPtr()->GetDebugger();
diff --git a/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py b/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py
new file mode 100644
index 00000000000000..b0d0b7a8dfe4e7
--- /dev/null
+++ b/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py
@@ -0,0 +1,17 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SBCommandReturnObjectTest(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test(self):
+ res = lldb.SBCommandReturnObject()
+ self.assertEqual(res.GetCommand(), "")
+
+ ci = self.dbg.GetCommandInterpreter()
+ ci.HandleCommand("help help", res)
+ self.assertTrue(res.Succeeded())
+ self.assertEqual(res.GetCommand(), "help help")
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 1960240dc41514..a372ed00baa014 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -442,7 +442,7 @@ int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
std::string Command = substitute(Line);
P.formatLine("Command: {0}", Command);
- CommandReturnObject Result(/*colors*/ false);
+ CommandReturnObject Result("", /*colors*/ false);
if (!Dbg.GetCommandInterpreter().HandleCommand(
Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
P.formatLine("Failed: {0}", Result.GetErrorString());
@@ -1189,7 +1189,7 @@ int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) {
// Set up a Process. In order to allocate memory within a target, this
// process must be alive and must support JIT'ing.
- CommandReturnObject Result(/*colors*/ false);
+ CommandReturnObject Result("", /*colors*/ false);
Dbg.SetAsyncExecution(false);
CommandInterpreter &CI = Dbg.GetCommandInterpreter();
auto IssueCmd = [&](const char *Cmd) -> bool {
@@ -1258,7 +1258,7 @@ int main(int argc, const char *argv[]) {
auto Dbg = lldb_private::Debugger::CreateInstance();
ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false);
- CommandReturnObject Result(/*colors*/ false);
+ CommandReturnObject Result("", /*colors*/ false);
Dbg->GetCommandInterpreter().HandleCommand(
"settings set plugin.process.gdb-remote.packet-timeout 60",
/*add_to_history*/ eLazyBoolNo, Result);
More information about the lldb-commits
mailing list