xref: /llvm-project/lldb/source/Commands/CommandObjectExpression.cpp (revision d77c2e09266304864ca95434bb8f4eb1605f057a)
1 //===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/STLExtras.h"
10 #include "llvm/ADT/StringRef.h"
11 
12 #include "CommandObjectExpression.h"
13 #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
14 #include "lldb/Core/Debugger.h"
15 #include "lldb/Core/Value.h"
16 #include "lldb/Core/ValueObjectVariable.h"
17 #include "lldb/DataFormatters/ValueObjectPrinter.h"
18 #include "lldb/Expression/DWARFExpression.h"
19 #include "lldb/Expression/REPL.h"
20 #include "lldb/Expression/UserExpression.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Host/OptionParser.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Interpreter/OptionArgParser.h"
26 #include "lldb/Symbol/ObjectFile.h"
27 #include "lldb/Symbol/Variable.h"
28 #include "lldb/Target/Language.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/StackFrame.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Target/Thread.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {}
38 
39 CommandObjectExpression::CommandOptions::~CommandOptions() = default;
40 
41 static constexpr OptionEnumValueElement g_description_verbosity_type[] = {
42     {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact",
43      "Only show the description string"},
44     {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full",
45      "Show the full output, including persistent variable's name and type"} };
46 
47 static constexpr OptionEnumValues DescriptionVerbosityTypes() {
48   return OptionEnumValues(g_description_verbosity_type);
49 }
50 
51 static constexpr OptionDefinition g_expression_options[] = {
52     // clang-format off
53   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads",           'a', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeBoolean,              "Should we run all threads if the execution doesn't complete on one thread."},
54   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints",    'i', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeBoolean,              "Ignore breakpoint hits while running expressions"},
55   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",               't', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeUnsignedInteger,      "Timeout value (in microseconds) for running the expression."},
56   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error",       'u', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeBoolean,              "Clean up program state if the expression causes a crash, or raises a signal.  "
57                                                                                                                                                                                   "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
58   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug",                 'g', OptionParser::eNoArgument,       nullptr, {},                          0, eArgTypeNone,                 "When specified, debug the JIT code by setting a breakpoint on the first instruction "
59                                                                                                                                                                                   "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
60   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language",              'l', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeLanguage,             "Specifies the Language to use when parsing the expression.  If not set the target.language "
61                                                                                                                                                                                   "setting is used." },
62   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits",          'X', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeLanguage,             "If true, simple fix-it hints will be automatically applied to the expression." },
63   {LLDB_OPT_SET_1,                  false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
64   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level",             'p', OptionParser::eNoArgument,       nullptr, {},                          0, eArgTypeNone,                 "Interpret the expression as a complete translation unit, without injecting it into the local "
65                                                                                                                                                                                   "context.  Allows declaration of persistent, top-level entities without a $ prefix."},
66   {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit",             'j', OptionParser::eRequiredArgument, nullptr, {},                          0, eArgTypeBoolean,              "Controls whether the expression can fall back to being JITted if it's not supported by "
67                                                                                                                                                                                   "the interpreter (defaults to true)."}
68     // clang-format on
69 };
70 
71 Status CommandObjectExpression::CommandOptions::SetOptionValue(
72     uint32_t option_idx, llvm::StringRef option_arg,
73     ExecutionContext *execution_context) {
74   Status error;
75 
76   const int short_option = GetDefinitions()[option_idx].short_option;
77 
78   switch (short_option) {
79   case 'l':
80     language = Language::GetLanguageTypeFromString(option_arg);
81     if (language == eLanguageTypeUnknown)
82       error.SetErrorStringWithFormat(
83           "unknown language type: '%s' for expression",
84           option_arg.str().c_str());
85     break;
86 
87   case 'a': {
88     bool success;
89     bool result;
90     result = OptionArgParser::ToBoolean(option_arg, true, &success);
91     if (!success)
92       error.SetErrorStringWithFormat(
93           "invalid all-threads value setting: \"%s\"",
94           option_arg.str().c_str());
95     else
96       try_all_threads = result;
97   } break;
98 
99   case 'i': {
100     bool success;
101     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
102     if (success)
103       ignore_breakpoints = tmp_value;
104     else
105       error.SetErrorStringWithFormat(
106           "could not convert \"%s\" to a boolean value.",
107           option_arg.str().c_str());
108     break;
109   }
110 
111   case 'j': {
112     bool success;
113     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
114     if (success)
115       allow_jit = tmp_value;
116     else
117       error.SetErrorStringWithFormat(
118           "could not convert \"%s\" to a boolean value.",
119           option_arg.str().c_str());
120     break;
121   }
122 
123   case 't':
124     if (option_arg.getAsInteger(0, timeout)) {
125       timeout = 0;
126       error.SetErrorStringWithFormat("invalid timeout setting \"%s\"",
127                                      option_arg.str().c_str());
128     }
129     break;
130 
131   case 'u': {
132     bool success;
133     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
134     if (success)
135       unwind_on_error = tmp_value;
136     else
137       error.SetErrorStringWithFormat(
138           "could not convert \"%s\" to a boolean value.",
139           option_arg.str().c_str());
140     break;
141   }
142 
143   case 'v':
144     if (option_arg.empty()) {
145       m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
146       break;
147     }
148     m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
149         OptionArgParser::ToOptionEnum(
150             option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
151     if (!error.Success())
152       error.SetErrorStringWithFormat(
153           "unrecognized value for description-verbosity '%s'",
154           option_arg.str().c_str());
155     break;
156 
157   case 'g':
158     debug = true;
159     unwind_on_error = false;
160     ignore_breakpoints = false;
161     break;
162 
163   case 'p':
164     top_level = true;
165     break;
166 
167   case 'X': {
168     bool success;
169     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
170     if (success)
171       auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
172     else
173       error.SetErrorStringWithFormat(
174           "could not convert \"%s\" to a boolean value.",
175           option_arg.str().c_str());
176     break;
177   }
178 
179   default:
180     error.SetErrorStringWithFormat("invalid short option character '%c'",
181                                    short_option);
182     break;
183   }
184 
185   return error;
186 }
187 
188 void CommandObjectExpression::CommandOptions::OptionParsingStarting(
189     ExecutionContext *execution_context) {
190   auto process_sp =
191       execution_context ? execution_context->GetProcessSP() : ProcessSP();
192   if (process_sp) {
193     ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions();
194     unwind_on_error = process_sp->GetUnwindOnErrorInExpressions();
195   } else {
196     ignore_breakpoints = true;
197     unwind_on_error = true;
198   }
199 
200   show_summary = true;
201   try_all_threads = true;
202   timeout = 0;
203   debug = false;
204   language = eLanguageTypeUnknown;
205   m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
206   auto_apply_fixits = eLazyBoolCalculate;
207   top_level = false;
208   allow_jit = true;
209 }
210 
211 llvm::ArrayRef<OptionDefinition>
212 CommandObjectExpression::CommandOptions::GetDefinitions() {
213   return llvm::makeArrayRef(g_expression_options);
214 }
215 
216 CommandObjectExpression::CommandObjectExpression(
217     CommandInterpreter &interpreter)
218     : CommandObjectRaw(
219           interpreter, "expression", "Evaluate an expression on the current "
220                                      "thread.  Displays any returned value "
221                                      "with LLDB's default formatting.",
222           "", eCommandProcessMustBePaused | eCommandTryTargetAPILock),
223       IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
224       m_option_group(), m_format_options(eFormatDefault),
225       m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
226                     true),
227       m_command_options(), m_expr_line_count(0), m_expr_lines() {
228   SetHelpLong(
229       R"(
230 Single and multi-line expressions:
231 
232 )"
233       "    The expression provided on the command line must be a complete expression \
234 with no newlines.  To evaluate a multi-line expression, \
235 hit a return after an empty expression, and lldb will enter the multi-line expression editor. \
236 Hit return on an empty line to end the multi-line expression."
237 
238       R"(
239 
240 Timeouts:
241 
242 )"
243       "    If the expression can be evaluated statically (without running code) then it will be.  \
244 Otherwise, by default the expression will run on the current thread with a short timeout: \
245 currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted \
246 and resumed with all threads running.  You can use the -a option to disable retrying on all \
247 threads.  You can use the -t option to set a shorter timeout."
248       R"(
249 
250 User defined variables:
251 
252 )"
253       "    You can define your own variables for convenience or to be used in subsequent expressions.  \
254 You define them the same way you would define variables in C.  If the first character of \
255 your user defined variable is a $, then the variable's value will be available in future \
256 expressions, otherwise it will just be available in the current expression."
257       R"(
258 
259 Continuing evaluation after a breakpoint:
260 
261 )"
262       "    If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
263 you are done with your investigation, you can either remove the expression execution frames \
264 from the stack with \"thread return -x\" or if you are still interested in the expression result \
265 you can issue the \"continue\" command and the expression evaluation will complete and the \
266 expression result will be available using the \"thread.completed-expression\" key in the thread \
267 format."
268 
269       R"(
270 
271 Examples:
272 
273     expr my_struct->a = my_array[3]
274     expr -f bin -- (index * 8) + 5
275     expr unsigned int $foo = 5
276     expr char c[] = \"foo\"; c[0])");
277 
278   CommandArgumentEntry arg;
279   CommandArgumentData expression_arg;
280 
281   // Define the first (and only) variant of this arg.
282   expression_arg.arg_type = eArgTypeExpression;
283   expression_arg.arg_repetition = eArgRepeatPlain;
284 
285   // There is only one variant this argument could be; put it into the argument
286   // entry.
287   arg.push_back(expression_arg);
288 
289   // Push the data for the first argument into the m_arguments vector.
290   m_arguments.push_back(arg);
291 
292   // Add the "--format" and "--gdb-format"
293   m_option_group.Append(&m_format_options,
294                         OptionGroupFormat::OPTION_GROUP_FORMAT |
295                             OptionGroupFormat::OPTION_GROUP_GDB_FMT,
296                         LLDB_OPT_SET_1);
297   m_option_group.Append(&m_command_options);
298   m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL,
299                         LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
300   m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
301   m_option_group.Finalize();
302 }
303 
304 CommandObjectExpression::~CommandObjectExpression() = default;
305 
306 Options *CommandObjectExpression::GetOptions() { return &m_option_group; }
307 
308 int CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
309   EvaluateExpressionOptions options;
310   options.SetCoerceToId(m_varobj_options.use_objc);
311   options.SetLanguage(m_command_options.language);
312   options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever);
313   options.SetAutoApplyFixIts(false);
314   options.SetGenerateDebugInfo(false);
315 
316   // We need a valid execution context with a frame pointer for this
317   // completion, so if we don't have one we should try to make a valid
318   // execution context.
319   if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
320     m_interpreter.UpdateExecutionContext(nullptr);
321 
322   // This didn't work, so let's get out before we start doing things that
323   // expect a valid frame pointer.
324   if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
325     return 0;
326 
327   ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
328 
329   Target *target = exe_ctx.GetTargetPtr();
330 
331   if (!target)
332     target = GetDummyTarget();
333 
334   if (!target)
335     return 0;
336 
337   unsigned cursor_pos = request.GetRawCursorPos();
338   llvm::StringRef code = request.GetRawLine();
339 
340   const std::size_t original_code_size = code.size();
341 
342   // Remove the first token which is 'expr' or some alias/abbreviation of that.
343   code = llvm::getToken(code).second.ltrim();
344   OptionsWithRaw args(code);
345   code = args.GetRawPart();
346 
347   // The position where the expression starts in the command line.
348   assert(original_code_size >= code.size());
349   std::size_t raw_start = original_code_size - code.size();
350 
351   // Check if the cursor is actually in the expression string, and if not, we
352   // exit.
353   // FIXME: We should complete the options here.
354   if (cursor_pos < raw_start)
355     return 0;
356 
357   // Make the cursor_pos again relative to the start of the code string.
358   assert(cursor_pos >= raw_start);
359   cursor_pos -= raw_start;
360 
361   auto language = exe_ctx.GetFrameRef().GetLanguage();
362 
363   Status error;
364   lldb::UserExpressionSP expr(target->GetUserExpressionForLanguage(
365       code, llvm::StringRef(), language, UserExpression::eResultTypeAny,
366       options, nullptr, error));
367   if (error.Fail())
368     return 0;
369 
370   expr->Complete(exe_ctx, request, cursor_pos);
371   return request.GetNumberOfMatches();
372 }
373 
374 static lldb_private::Status
375 CanBeUsedForElementCountPrinting(ValueObject &valobj) {
376   CompilerType type(valobj.GetCompilerType());
377   CompilerType pointee;
378   if (!type.IsPointerType(&pointee))
379     return Status("as it does not refer to a pointer");
380   if (pointee.IsVoidType())
381     return Status("as it refers to a pointer to void");
382   return Status();
383 }
384 
385 bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
386                                                  Stream *output_stream,
387                                                  Stream *error_stream,
388                                                  CommandReturnObject *result) {
389   // Don't use m_exe_ctx as this might be called asynchronously after the
390   // command object DoExecute has finished when doing multi-line expression
391   // that use an input reader...
392   ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
393 
394   Target *target = exe_ctx.GetTargetPtr();
395 
396   if (!target)
397     target = GetDummyTarget();
398 
399   if (target) {
400     lldb::ValueObjectSP result_valobj_sp;
401     bool keep_in_memory = true;
402     StackFrame *frame = exe_ctx.GetFramePtr();
403 
404     EvaluateExpressionOptions options;
405     options.SetCoerceToId(m_varobj_options.use_objc);
406     options.SetUnwindOnError(m_command_options.unwind_on_error);
407     options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints);
408     options.SetKeepInMemory(keep_in_memory);
409     options.SetUseDynamic(m_varobj_options.use_dynamic);
410     options.SetTryAllThreads(m_command_options.try_all_threads);
411     options.SetDebug(m_command_options.debug);
412     options.SetLanguage(m_command_options.language);
413     options.SetExecutionPolicy(
414         m_command_options.allow_jit
415             ? EvaluateExpressionOptions::default_execution_policy
416             : lldb_private::eExecutionPolicyNever);
417 
418     bool auto_apply_fixits;
419     if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
420       auto_apply_fixits = target->GetEnableAutoApplyFixIts();
421     else
422       auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes;
423 
424     options.SetAutoApplyFixIts(auto_apply_fixits);
425 
426     if (m_command_options.top_level)
427       options.SetExecutionPolicy(eExecutionPolicyTopLevel);
428 
429     // If there is any chance we are going to stop and want to see what went
430     // wrong with our expression, we should generate debug info
431     if (!m_command_options.ignore_breakpoints ||
432         !m_command_options.unwind_on_error)
433       options.SetGenerateDebugInfo(true);
434 
435     if (m_command_options.timeout > 0)
436       options.SetTimeout(std::chrono::microseconds(m_command_options.timeout));
437     else
438       options.SetTimeout(llvm::None);
439 
440     ExpressionResults success = target->EvaluateExpression(
441         expr, frame, result_valobj_sp, options, &m_fixed_expression);
442 
443     // We only tell you about the FixIt if we applied it.  The compiler errors
444     // will suggest the FixIt if it parsed.
445     if (error_stream && !m_fixed_expression.empty() &&
446         target->GetEnableNotifyAboutFixIts()) {
447       if (success == eExpressionCompleted)
448         error_stream->Printf(
449             "  Fix-it applied, fixed expression was: \n    %s\n",
450             m_fixed_expression.c_str());
451     }
452 
453     if (result_valobj_sp) {
454       Format format = m_format_options.GetFormat();
455 
456       if (result_valobj_sp->GetError().Success()) {
457         if (format != eFormatVoid) {
458           if (format != eFormatDefault)
459             result_valobj_sp->SetFormat(format);
460 
461           if (m_varobj_options.elem_count > 0) {
462             Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
463             if (error.Fail()) {
464               result->AppendErrorWithFormat(
465                   "expression cannot be used with --element-count %s\n",
466                   error.AsCString(""));
467               result->SetStatus(eReturnStatusFailed);
468               return false;
469             }
470           }
471 
472           DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
473               m_command_options.m_verbosity, format));
474           options.SetVariableFormatDisplayLanguage(
475               result_valobj_sp->GetPreferredDisplayLanguage());
476 
477           result_valobj_sp->Dump(*output_stream, options);
478 
479           if (result)
480             result->SetStatus(eReturnStatusSuccessFinishResult);
481         }
482       } else {
483         if (result_valobj_sp->GetError().GetError() ==
484             UserExpression::kNoResult) {
485           if (format != eFormatVoid &&
486               m_interpreter.GetDebugger().GetNotifyVoid()) {
487             error_stream->PutCString("(void)\n");
488           }
489 
490           if (result)
491             result->SetStatus(eReturnStatusSuccessFinishResult);
492         } else {
493           const char *error_cstr = result_valobj_sp->GetError().AsCString();
494           if (error_cstr && error_cstr[0]) {
495             const size_t error_cstr_len = strlen(error_cstr);
496             const bool ends_with_newline =
497                 error_cstr[error_cstr_len - 1] == '\n';
498             if (strstr(error_cstr, "error:") != error_cstr)
499               error_stream->PutCString("error: ");
500             error_stream->Write(error_cstr, error_cstr_len);
501             if (!ends_with_newline)
502               error_stream->EOL();
503           } else {
504             error_stream->PutCString("error: unknown error\n");
505           }
506 
507           if (result)
508             result->SetStatus(eReturnStatusFailed);
509         }
510       }
511     }
512   } else {
513     error_stream->Printf("error: invalid execution context for expression\n");
514     return false;
515   }
516 
517   return true;
518 }
519 
520 void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
521                                                      std::string &line) {
522   io_handler.SetIsDone(true);
523   //    StreamSP output_stream =
524   //    io_handler.GetDebugger().GetAsyncOutputStream();
525   //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
526   StreamFileSP output_sp(io_handler.GetOutputStreamFile());
527   StreamFileSP error_sp(io_handler.GetErrorStreamFile());
528 
529   EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get());
530   if (output_sp)
531     output_sp->Flush();
532   if (error_sp)
533     error_sp->Flush();
534 }
535 
536 bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
537                                                        StringList &lines) {
538   // An empty lines is used to indicate the end of input
539   const size_t num_lines = lines.GetSize();
540   if (num_lines > 0 && lines[num_lines - 1].empty()) {
541     // Remove the last empty line from "lines" so it doesn't appear in our
542     // resulting input and return true to indicate we are done getting lines
543     lines.PopBack();
544     return true;
545   }
546   return false;
547 }
548 
549 void CommandObjectExpression::GetMultilineExpression() {
550   m_expr_lines.clear();
551   m_expr_line_count = 0;
552 
553   Debugger &debugger = GetCommandInterpreter().GetDebugger();
554   bool color_prompt = debugger.GetUseColor();
555   const bool multiple_lines = true; // Get multiple lines
556   IOHandlerSP io_handler_sp(
557       new IOHandlerEditline(debugger, IOHandler::Type::Expression,
558                             "lldb-expr", // Name of input reader for history
559                             llvm::StringRef(), // No prompt
560                             llvm::StringRef(), // Continuation prompt
561                             multiple_lines, color_prompt,
562                             1, // Show line numbers starting at 1
563                             *this, nullptr));
564 
565   StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
566   if (output_sp) {
567     output_sp->PutCString(
568         "Enter expressions, then terminate with an empty line to evaluate:\n");
569     output_sp->Flush();
570   }
571   debugger.PushIOHandler(io_handler_sp);
572 }
573 
574 bool CommandObjectExpression::DoExecute(llvm::StringRef command,
575                                         CommandReturnObject &result) {
576   m_fixed_expression.clear();
577   auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
578   m_option_group.NotifyOptionParsingStarting(&exe_ctx);
579 
580   if (command.empty()) {
581     GetMultilineExpression();
582     return result.Succeeded();
583   }
584 
585   OptionsWithRaw args(command);
586   llvm::StringRef expr = args.GetRawPart();
587 
588   if (args.HasArgs()) {
589     if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx))
590       return false;
591 
592     if (m_repl_option.GetOptionValue().GetCurrentValue()) {
593       Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
594       if (target) {
595         // Drop into REPL
596         m_expr_lines.clear();
597         m_expr_line_count = 0;
598 
599         Debugger &debugger = target->GetDebugger();
600 
601         // Check if the LLDB command interpreter is sitting on top of a REPL
602         // that launched it...
603         if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
604                                             IOHandler::Type::REPL)) {
605           // the LLDB command interpreter is sitting on top of a REPL that
606           // launched it, so just say the command interpreter is done and
607           // fall back to the existing REPL
608           m_interpreter.GetIOHandler(false)->SetIsDone(true);
609         } else {
610           // We are launching the REPL on top of the current LLDB command
611           // interpreter, so just push one
612           bool initialize = false;
613           Status repl_error;
614           REPLSP repl_sp(target->GetREPL(repl_error, m_command_options.language,
615                                          nullptr, false));
616 
617           if (!repl_sp) {
618             initialize = true;
619             repl_sp = target->GetREPL(repl_error, m_command_options.language,
620                                       nullptr, true);
621             if (!repl_error.Success()) {
622               result.SetError(repl_error);
623               return result.Succeeded();
624             }
625           }
626 
627           if (repl_sp) {
628             if (initialize) {
629               repl_sp->SetCommandOptions(m_command_options);
630               repl_sp->SetFormatOptions(m_format_options);
631               repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
632             }
633 
634             IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
635 
636             io_handler_sp->SetIsDone(false);
637 
638             debugger.PushIOHandler(io_handler_sp);
639           } else {
640             repl_error.SetErrorStringWithFormat(
641                 "Couldn't create a REPL for %s",
642                 Language::GetNameForLanguageType(m_command_options.language));
643             result.SetError(repl_error);
644             return result.Succeeded();
645           }
646         }
647       }
648     }
649     // No expression following options
650     else if (expr.empty()) {
651       GetMultilineExpression();
652       return result.Succeeded();
653     }
654   }
655 
656   Target *target = GetSelectedOrDummyTarget();
657   if (EvaluateExpression(expr, &(result.GetOutputStream()),
658                          &(result.GetErrorStream()), &result)) {
659 
660     if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) {
661       CommandHistory &history = m_interpreter.GetCommandHistory();
662       // FIXME: Can we figure out what the user actually typed (e.g. some alias
663       // for expr???)
664       // If we can it would be nice to show that.
665       std::string fixed_command("expression ");
666       if (args.HasArgs()) {
667         // Add in any options that might have been in the original command:
668         fixed_command.append(args.GetArgStringWithDelimiter());
669         fixed_command.append(m_fixed_expression);
670       } else
671         fixed_command.append(m_fixed_expression);
672       history.AppendString(fixed_command);
673     }
674     // Increment statistics to record this expression evaluation success.
675     target->IncrementStats(StatisticKind::ExpressionSuccessful);
676     return true;
677   }
678 
679   // Increment statistics to record this expression evaluation failure.
680   target->IncrementStats(StatisticKind::ExpressionFailure);
681   result.SetStatus(eReturnStatusFailed);
682   return false;
683 }
684