Skip to content

Commit 6deee0d

Browse files
authored
[lldb] Use llvm::Error instead of CommandReturnObject for error reporting (#125125)
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.
1 parent e6d12ad commit 6deee0d

File tree

6 files changed

+99
-83
lines changed

6 files changed

+99
-83
lines changed

lldb/include/lldb/Interpreter/Options.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ class Options {
7676
// This gets passed the short option as an integer...
7777
void OptionSeen(int short_option);
7878

79-
bool VerifyOptions(CommandReturnObject &result);
79+
llvm::Error VerifyOptions();
8080

8181
// Verify that the options given are in the options table and can be used
8282
// together, but there may be some required options that are missing (used to
8383
// verify options that get folded into command aliases).
84-
bool VerifyPartialOptions(CommandReturnObject &result);
84+
llvm::Error VerifyPartialOptions();
8585

8686
void OutputFormattedUsageText(Stream &strm,
8787
const OptionDefinition &option_def,

lldb/source/Interpreter/CommandAlias.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "llvm/ADT/STLExtras.h"
1212
#include "llvm/Support/ErrorHandling.h"
13+
#include "llvm/Support/FormatAdapters.h"
1314

1415
#include "lldb/Interpreter/CommandInterpreter.h"
1516
#include "lldb/Interpreter/CommandObject.h"
@@ -20,20 +21,17 @@
2021
using namespace lldb;
2122
using namespace lldb_private;
2223

23-
static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
24-
llvm::StringRef options_args,
25-
OptionArgVectorSP &option_arg_vector_sp) {
26-
bool success = true;
24+
static llvm::Error
25+
ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
26+
llvm::StringRef options_args,
27+
OptionArgVectorSP &option_arg_vector_sp) {
2728
OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2829

2930
if (options_args.size() < 1)
30-
return true;
31+
return llvm::Error::success();
3132

3233
Args args(options_args);
3334
std::string options_string(options_args);
34-
// TODO: Find a way to propagate errors in this CommandReturnObject up the
35-
// stack.
36-
CommandReturnObject result(false);
3735
// Check to see if the command being aliased can take any command options.
3836
Options *options = cmd_obj_sp->GetOptions();
3937
if (options) {
@@ -45,34 +43,30 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
4543

4644
llvm::Expected<Args> args_or =
4745
options->ParseAlias(args, option_arg_vector, options_string);
48-
if (!args_or) {
49-
result.AppendError(toString(args_or.takeError()));
50-
result.AppendError("Unable to create requested alias.\n");
51-
return false;
52-
}
46+
if (!args_or)
47+
return llvm::createStringError(
48+
llvm::formatv("unable to create alias: {0}",
49+
llvm::fmt_consume(args_or.takeError())));
5350
args = std::move(*args_or);
54-
options->VerifyPartialOptions(result);
55-
if (!result.Succeeded() &&
56-
result.GetStatus() != lldb::eReturnStatusStarted) {
57-
result.AppendError("Unable to create requested alias.\n");
58-
return false;
59-
}
51+
if (llvm::Error error = options->VerifyPartialOptions())
52+
return error;
6053
}
6154

6255
if (!options_string.empty()) {
63-
if (cmd_obj_sp->WantsRawCommandString())
64-
option_arg_vector->emplace_back(CommandInterpreter::g_argument,
65-
-1, options_string);
66-
else {
56+
if (cmd_obj_sp->WantsRawCommandString()) {
57+
option_arg_vector->emplace_back(CommandInterpreter::g_argument, -1,
58+
options_string);
59+
} else {
6760
for (auto &entry : args.entries()) {
6861
if (!entry.ref().empty())
69-
option_arg_vector->emplace_back(std::string(CommandInterpreter::g_argument), -1,
70-
std::string(entry.ref()));
62+
option_arg_vector->emplace_back(
63+
std::string(CommandInterpreter::g_argument), -1,
64+
std::string(entry.ref()));
7165
}
7266
}
7367
}
7468

75-
return success;
69+
return llvm::Error::success();
7670
}
7771

7872
CommandAlias::CommandAlias(CommandInterpreter &interpreter,
@@ -85,10 +79,15 @@ CommandAlias::CommandAlias(CommandInterpreter &interpreter,
8579
m_option_args_sp(new OptionArgVector),
8680
m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
8781
m_did_set_help_long(false) {
88-
if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
82+
if (llvm::Error error =
83+
ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
84+
// FIXME: Find a way to percolate this error up.
85+
LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(error),
86+
"ProcessAliasOptionsArgs failed: {0}");
87+
} else {
8988
m_underlying_command_sp = cmd_sp;
9089
for (int i = 0;
91-
auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
90+
auto *cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
9291
i++) {
9392
m_arguments.push_back(*cmd_entry);
9493
}

lldb/source/Interpreter/CommandObject.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,24 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
120120
if (args_or) {
121121
args = std::move(*args_or);
122122
error = options->NotifyOptionParsingFinished(&exe_ctx);
123-
} else
123+
} else {
124124
error = Status::FromError(args_or.takeError());
125+
}
125126

126-
if (error.Success()) {
127-
if (options->VerifyOptions(result))
128-
return true;
129-
} else {
127+
if (error.Fail()) {
130128
result.SetError(error.takeError());
129+
result.SetStatus(eReturnStatusFailed);
130+
return false;
131131
}
132-
result.SetStatus(eReturnStatusFailed);
133-
return false;
132+
133+
if (llvm::Error error = options->VerifyOptions()) {
134+
result.SetError(std::move(error));
135+
result.SetStatus(eReturnStatusFailed);
136+
return false;
137+
}
138+
139+
result.SetStatus(eReturnStatusSuccessFinishNoResult);
140+
return true;
134141
}
135142
return true;
136143
}

lldb/source/Interpreter/Options.cpp

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -138,46 +138,6 @@ void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
138138
}
139139
}
140140

141-
bool Options::VerifyOptions(CommandReturnObject &result) {
142-
bool options_are_valid = false;
143-
144-
int num_levels = GetRequiredOptions().size();
145-
if (num_levels) {
146-
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
147-
// This is the correct set of options if: 1). m_seen_options contains
148-
// all of m_required_options[i] (i.e. all the required options at this
149-
// level are a subset of m_seen_options); AND 2). { m_seen_options -
150-
// m_required_options[i] is a subset of m_options_options[i] (i.e. all
151-
// the rest of m_seen_options are in the set of optional options at this
152-
// level.
153-
154-
// Check to see if all of m_required_options[i] are a subset of
155-
// m_seen_options
156-
if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
157-
// Construct the set difference: remaining_options = {m_seen_options} -
158-
// {m_required_options[i]}
159-
OptionSet remaining_options;
160-
OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
161-
remaining_options);
162-
// Check to see if remaining_options is a subset of
163-
// m_optional_options[i]
164-
if (IsASubset(remaining_options, GetOptionalOptions()[i]))
165-
options_are_valid = true;
166-
}
167-
}
168-
} else {
169-
options_are_valid = true;
170-
}
171-
172-
if (options_are_valid) {
173-
result.SetStatus(eReturnStatusSuccessFinishNoResult);
174-
} else {
175-
result.AppendError("invalid combination of options for the given command");
176-
}
177-
178-
return options_are_valid;
179-
}
180-
181141
// This is called in the Options constructor, though we could call it lazily if
182142
// that ends up being a performance problem.
183143

@@ -590,13 +550,50 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject &cmd,
590550
strm.SetIndentLevel(save_indent_level);
591551
}
592552

553+
llvm::Error Options::VerifyOptions() {
554+
bool options_are_valid = false;
555+
556+
int num_levels = GetRequiredOptions().size();
557+
if (num_levels) {
558+
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
559+
// This is the correct set of options if: 1). m_seen_options contains
560+
// all of m_required_options[i] (i.e. all the required options at this
561+
// level are a subset of m_seen_options); AND 2). { m_seen_options -
562+
// m_required_options[i] is a subset of m_options_options[i] (i.e. all
563+
// the rest of m_seen_options are in the set of optional options at this
564+
// level.
565+
566+
// Check to see if all of m_required_options[i] are a subset of
567+
// m_seen_options
568+
if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
569+
// Construct the set difference: remaining_options = {m_seen_options} -
570+
// {m_required_options[i]}
571+
OptionSet remaining_options;
572+
OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
573+
remaining_options);
574+
// Check to see if remaining_options is a subset of
575+
// m_optional_options[i]
576+
if (IsASubset(remaining_options, GetOptionalOptions()[i]))
577+
options_are_valid = true;
578+
}
579+
}
580+
} else {
581+
options_are_valid = true;
582+
}
583+
584+
if (!options_are_valid)
585+
return llvm::createStringError(
586+
"invalid combination of options for the given command");
587+
588+
return llvm::Error::success();
589+
}
590+
593591
// This function is called when we have been given a potentially incomplete set
594592
// of options, such as when an alias has been defined (more options might be
595593
// added at at the time the alias is invoked). We need to verify that the
596594
// options in the set m_seen_options are all part of a set that may be used
597595
// together, but m_seen_options may be missing some of the "required" options.
598-
599-
bool Options::VerifyPartialOptions(CommandReturnObject &result) {
596+
llvm::Error Options::VerifyPartialOptions() {
600597
bool options_are_valid = false;
601598

602599
int num_levels = GetRequiredOptions().size();
@@ -613,7 +610,11 @@ bool Options::VerifyPartialOptions(CommandReturnObject &result) {
613610
}
614611
}
615612

616-
return options_are_valid;
613+
if (!options_are_valid)
614+
return llvm::createStringError(
615+
"invalid combination of options for the given command");
616+
617+
return llvm::Error::success();
617618
}
618619

619620
bool Options::HandleOptionCompletion(CompletionRequest &request,

lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -975,8 +975,6 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
975975
EnableOptionsSP options_sp(new EnableOptions());
976976
options_sp->NotifyOptionParsingStarting(&exe_ctx);
977977

978-
CommandReturnObject result(debugger.GetUseColor());
979-
980978
// Parse the arguments.
981979
auto options_property_sp =
982980
debugger.GetPropertyValue(nullptr,
@@ -1013,8 +1011,13 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
10131011
return EnableOptionsSP();
10141012
}
10151013

1016-
if (!options_sp->VerifyOptions(result))
1014+
if (llvm::Error error = options_sp->VerifyOptions()) {
1015+
LLDB_LOG_ERROR(
1016+
log, std::move(error),
1017+
"Parsing plugin.structured-data.darwin-log.auto-enable-options value "
1018+
"failed: {0}");
10171019
return EnableOptionsSP();
1020+
}
10181021

10191022
// We successfully parsed and validated the options.
10201023
return options_sp;

lldb/test/API/functionalities/abbreviation/TestAbbreviations.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ def test_command_abbreviations_and_aliases(self):
9494
self.assertTrue(result.Succeeded())
9595
self.assertEqual("scripting run 1+1", result.GetOutput())
9696

97+
# Name and line are incompatible options.
98+
command_interpreter.HandleCommand(
99+
"alias zzyx breakpoint set -n %1 -l %2", result
100+
)
101+
self.assertFalse(result.Succeeded())
102+
97103
# Prompt changing stuff should be tested, but this doesn't seem like the
98104
# right test to do it in. It has nothing to do with aliases or abbreviations.
99105
# self.runCmd("com sou ./change_prompt.lldb")

0 commit comments

Comments
 (0)