summaryrefslogtreecommitdiff
path: root/source/Commands/CommandObjectExpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Commands/CommandObjectExpression.cpp')
-rw-r--r--source/Commands/CommandObjectExpression.cpp234
1 files changed, 155 insertions, 79 deletions
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 7f0b03b37c20a..f2bd3ed367caf 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "CommandObjectExpression.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+
// Project includes
+#include "CommandObjectExpression.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
@@ -32,8 +34,6 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
using namespace lldb;
using namespace lldb_private;
@@ -43,31 +43,30 @@ CommandObjectExpression::CommandOptions::CommandOptions () :
{
}
-
-CommandObjectExpression::CommandOptions::~CommandOptions ()
-{
-}
+CommandObjectExpression::CommandOptions::~CommandOptions() = default;
static OptionEnumValueElement g_description_verbosity_type[] =
{
{ eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"},
{ eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
OptionDefinition
CommandObjectExpression::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." },
- { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, NULL, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." },
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." },
+ { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Interpret the expression as top-level definitions rather than code to be immediately executed."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by the interpreter (defaults to true)."}
};
-
uint32_t
CommandObjectExpression::CommandOptions::GetNumDefinitions ()
{
@@ -113,6 +112,18 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
break;
}
+
+ case 'j':
+ {
+ bool success;
+ bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ if (success)
+ allow_jit = tmp_value;
+ else
+ error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
+ break;
+ }
+
case 't':
{
bool success;
@@ -152,7 +163,22 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
unwind_on_error = false;
ignore_breakpoints = false;
break;
+
+ case 'p':
+ top_level = true;
+ break;
+ case 'X':
+ {
+ bool success;
+ bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+ if (success)
+ auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
+ else
+ error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
+ break;
+ }
+
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
@@ -165,7 +191,7 @@ void
CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
{
Process *process = interpreter.GetExecutionContext().GetProcessPtr();
- if (process != NULL)
+ if (process != nullptr)
{
ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
unwind_on_error = process->GetUnwindOnErrorInExpressions();
@@ -182,6 +208,9 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
debug = false;
language = eLanguageTypeUnknown;
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
+ auto_apply_fixits = eLazyBoolCalculate;
+ top_level = false;
+ allow_jit = true;
}
const OptionDefinition*
@@ -190,19 +219,18 @@ CommandObjectExpression::CommandOptions::GetDefinitions ()
return g_option_table;
}
-CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
- CommandObjectRaw (interpreter,
- "expression",
- "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.",
- NULL,
- eCommandProcessMustBePaused | eCommandTryTargetAPILock),
- IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
- m_option_group (interpreter),
- m_format_options (eFormatDefault),
- m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true),
- m_command_options (),
- m_expr_line_count (0),
- m_expr_lines ()
+CommandObjectExpression::CommandObjectExpression(CommandInterpreter &interpreter)
+ : CommandObjectRaw(
+ interpreter, "expression",
+ "Evaluate an expression on the current thread. Displays any returned value with LLDB's default formatting.",
+ nullptr, eCommandProcessMustBePaused | eCommandTryTargetAPILock),
+ IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
+ m_option_group(interpreter),
+ m_format_options(eFormatDefault),
+ m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true),
+ m_command_options(),
+ m_expr_line_count(0),
+ m_expr_lines()
{
SetHelpLong(
R"(
@@ -259,9 +287,7 @@ Examples:
m_option_group.Finalize();
}
-CommandObjectExpression::~CommandObjectExpression ()
-{
-}
+CommandObjectExpression::~CommandObjectExpression() = default;
Options *
CommandObjectExpression::GetOptions ()
@@ -269,14 +295,23 @@ CommandObjectExpression::GetOptions ()
return &m_option_group;
}
+static lldb_private::Error
+CanBeUsedForElementCountPrinting (ValueObject& valobj)
+{
+ CompilerType type(valobj.GetCompilerType());
+ CompilerType pointee;
+ if (!type.IsPointerType(&pointee))
+ return Error("as it does not refer to a pointer");
+ if (pointee.IsVoidType())
+ return Error("as it refers to a pointer to void");
+ return Error();
+}
+
bool
-CommandObjectExpression::EvaluateExpression
-(
- const char *expr,
- Stream *output_stream,
- Stream *error_stream,
- CommandReturnObject *result
-)
+CommandObjectExpression::EvaluateExpression(const char *expr,
+ Stream *output_stream,
+ Stream *error_stream,
+ CommandReturnObject *result)
{
// Don't use m_exe_ctx as this might be called asynchronously
// after the command object DoExecute has finished when doing
@@ -303,6 +338,20 @@ CommandObjectExpression::EvaluateExpression
options.SetTryAllThreads(m_command_options.try_all_threads);
options.SetDebug(m_command_options.debug);
options.SetLanguage(m_command_options.language);
+ options.SetExecutionPolicy(m_command_options.allow_jit ?
+ EvaluateExpressionOptions::default_execution_policy :
+ lldb_private::eExecutionPolicyNever);
+
+ bool auto_apply_fixits;
+ if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
+ auto_apply_fixits = target->GetEnableAutoApplyFixIts();
+ else
+ auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;
+
+ options.SetAutoApplyFixIts(auto_apply_fixits);
+
+ if (m_command_options.top_level)
+ options.SetExecutionPolicy(eExecutionPolicyTopLevel);
// If there is any chance we are going to stop and want to see
// what went wrong with our expression, we should generate debug info
@@ -315,7 +364,14 @@ CommandObjectExpression::EvaluateExpression
else
options.SetTimeoutUsec(0);
- target->EvaluateExpression(expr, frame, result_valobj_sp, options);
+ ExpressionResults success = target->EvaluateExpression(expr, frame, result_valobj_sp, options, &m_fixed_expression);
+
+ // We only tell you about the FixIt if we applied it. The compiler errors will suggest the FixIt if it parsed.
+ if (error_stream && !m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
+ {
+ if (success == eExpressionCompleted)
+ error_stream->Printf (" Fix-it applied, fixed expression was: \n %s\n", m_fixed_expression.c_str());
+ }
if (result_valobj_sp)
{
@@ -328,6 +384,17 @@ CommandObjectExpression::EvaluateExpression
if (format != eFormatDefault)
result_valobj_sp->SetFormat (format);
+ if (m_varobj_options.elem_count > 0)
+ {
+ Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
+ if (error.Fail())
+ {
+ result->AppendErrorWithFormat("expression cannot be used with --element-count %s\n", error.AsCString(""));
+ result->SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage());
@@ -400,28 +467,21 @@ CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::str
error_sp->Flush();
}
-LineStatus
-CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
- StringList &lines,
- uint32_t line_idx,
- Error &error)
+bool
+CommandObjectExpression::IOHandlerIsInputComplete (IOHandler &io_handler,
+ StringList &lines)
{
- if (line_idx == UINT32_MAX)
+ // An empty lines is used to indicate the end of input
+ const size_t num_lines = lines.GetSize();
+ if (num_lines > 0 && lines[num_lines - 1].empty())
{
- // Remove the last line from "lines" so it doesn't appear
- // in our final expression
+ // Remove the last empty line from "lines" so it doesn't appear
+ // in our resulting input and return true to indicate we are done
+ // getting lines
lines.PopBack();
- error.Clear();
- return LineStatus::Done;
- }
- else if (line_idx + 1 == lines.GetSize())
- {
- // The last line was edited, if this line is empty, then we are done
- // getting our multiple lines.
- if (lines[line_idx].empty())
- return LineStatus::Done;
+ return true;
}
- return LineStatus::Success;
+ return false;
}
void
@@ -433,15 +493,15 @@ CommandObjectExpression::GetMultilineExpression ()
Debugger &debugger = GetCommandInterpreter().GetDebugger();
bool color_prompt = debugger.GetUseColor();
const bool multiple_lines = true; // Get multiple lines
- IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
- IOHandler::Type::Expression,
- "lldb-expr", // Name of input reader for history
- NULL, // No prompt
- NULL, // Continuation prompt
- multiple_lines,
- color_prompt,
- 1, // Show line numbers starting at 1
- *this));
+ IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
+ IOHandler::Type::Expression,
+ "lldb-expr", // Name of input reader for history
+ nullptr, // No prompt
+ nullptr, // Continuation prompt
+ multiple_lines,
+ color_prompt,
+ 1, // Show line numbers starting at 1
+ *this));
StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
if (output_sp)
@@ -453,15 +513,13 @@ CommandObjectExpression::GetMultilineExpression ()
}
bool
-CommandObjectExpression::DoExecute
-(
- const char *command,
- CommandReturnObject &result
-)
+CommandObjectExpression::DoExecute(const char *command,
+ CommandReturnObject &result)
{
+ m_fixed_expression.clear();
m_option_group.NotifyOptionParsingStarting();
- const char * expr = NULL;
+ const char * expr = nullptr;
if (command[0] == '\0')
{
@@ -472,7 +530,7 @@ CommandObjectExpression::DoExecute
if (command[0] == '-')
{
// We have some options and these options MUST end with --.
- const char *end_options = NULL;
+ const char *end_options = nullptr;
const char *s = command;
while (s && s[0])
{
@@ -568,7 +626,7 @@ CommandObjectExpression::DoExecute
}
}
// No expression following options
- else if (expr == NULL || expr[0] == '\0')
+ else if (expr == nullptr || expr[0] == '\0')
{
GetMultilineExpression ();
return result.Succeeded();
@@ -576,13 +634,31 @@ CommandObjectExpression::DoExecute
}
}
- if (expr == NULL)
+ if (expr == nullptr)
expr = command;
if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
+ {
+ Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
+ if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
+ {
+ CommandHistory &history = m_interpreter.GetCommandHistory();
+ // FIXME: Can we figure out what the user actually typed (e.g. some alias for expr???)
+ // If we can it would be nice to show that.
+ std::string fixed_command("expression ");
+ if (expr == command)
+ fixed_command.append(m_fixed_expression);
+ else
+ {
+ // Add in any options that might have been in the original command:
+ fixed_command.append(command, expr - command);
+ fixed_command.append(m_fixed_expression);
+ }
+ history.AppendString(fixed_command);
+ }
return true;
+ }
result.SetStatus (eReturnStatusFailed);
return false;
}
-