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