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 <jo...@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 <jo...@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 <jo...@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 <jo...@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); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits