xref: /openbsd-src/gnu/llvm/lldb/source/Expression/UserExpression.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- UserExpression.cpp ------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9be691f3bSpatrick #include <cstdio>
10061da546Spatrick #include <sys/types.h>
11061da546Spatrick 
12061da546Spatrick #include <cstdlib>
13061da546Spatrick #include <map>
14061da546Spatrick #include <string>
15061da546Spatrick 
16061da546Spatrick #include "lldb/Core/Module.h"
17061da546Spatrick #include "lldb/Core/StreamFile.h"
18061da546Spatrick #include "lldb/Core/ValueObjectConstResult.h"
19061da546Spatrick #include "lldb/Expression/DiagnosticManager.h"
20061da546Spatrick #include "lldb/Expression/ExpressionVariable.h"
21061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
22061da546Spatrick #include "lldb/Expression/IRInterpreter.h"
23061da546Spatrick #include "lldb/Expression/Materializer.h"
24061da546Spatrick #include "lldb/Expression/UserExpression.h"
25061da546Spatrick #include "lldb/Host/HostInfo.h"
26061da546Spatrick #include "lldb/Symbol/Block.h"
27061da546Spatrick #include "lldb/Symbol/Function.h"
28061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
29061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
30061da546Spatrick #include "lldb/Symbol/Type.h"
31061da546Spatrick #include "lldb/Symbol/TypeSystem.h"
32061da546Spatrick #include "lldb/Symbol/VariableList.h"
33061da546Spatrick #include "lldb/Target/ExecutionContext.h"
34061da546Spatrick #include "lldb/Target/Process.h"
35061da546Spatrick #include "lldb/Target/StackFrame.h"
36061da546Spatrick #include "lldb/Target/Target.h"
37061da546Spatrick #include "lldb/Target/ThreadPlan.h"
38061da546Spatrick #include "lldb/Target/ThreadPlanCallUserExpression.h"
39061da546Spatrick #include "lldb/Utility/ConstString.h"
40*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
41061da546Spatrick #include "lldb/Utility/Log.h"
42061da546Spatrick #include "lldb/Utility/StreamString.h"
43061da546Spatrick 
44061da546Spatrick using namespace lldb_private;
45061da546Spatrick 
46061da546Spatrick char UserExpression::ID;
47061da546Spatrick 
UserExpression(ExecutionContextScope & exe_scope,llvm::StringRef expr,llvm::StringRef prefix,lldb::LanguageType language,ResultType desired_type,const EvaluateExpressionOptions & options)48061da546Spatrick UserExpression::UserExpression(ExecutionContextScope &exe_scope,
49061da546Spatrick                                llvm::StringRef expr, llvm::StringRef prefix,
50061da546Spatrick                                lldb::LanguageType language,
51061da546Spatrick                                ResultType desired_type,
52061da546Spatrick                                const EvaluateExpressionOptions &options)
53dda28197Spatrick     : Expression(exe_scope), m_expr_text(std::string(expr)),
54dda28197Spatrick       m_expr_prefix(std::string(prefix)), m_language(language),
55dda28197Spatrick       m_desired_type(desired_type), m_options(options) {}
56061da546Spatrick 
57be691f3bSpatrick UserExpression::~UserExpression() = default;
58061da546Spatrick 
InstallContext(ExecutionContext & exe_ctx)59061da546Spatrick void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
60061da546Spatrick   m_jit_process_wp = exe_ctx.GetProcessSP();
61061da546Spatrick 
62061da546Spatrick   lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
63061da546Spatrick 
64061da546Spatrick   if (frame_sp)
65061da546Spatrick     m_address = frame_sp->GetFrameCodeAddress();
66061da546Spatrick }
67061da546Spatrick 
LockAndCheckContext(ExecutionContext & exe_ctx,lldb::TargetSP & target_sp,lldb::ProcessSP & process_sp,lldb::StackFrameSP & frame_sp)68061da546Spatrick bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
69061da546Spatrick                                          lldb::TargetSP &target_sp,
70061da546Spatrick                                          lldb::ProcessSP &process_sp,
71061da546Spatrick                                          lldb::StackFrameSP &frame_sp) {
72061da546Spatrick   lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
73061da546Spatrick   process_sp = exe_ctx.GetProcessSP();
74061da546Spatrick 
75061da546Spatrick   if (process_sp != expected_process_sp)
76061da546Spatrick     return false;
77061da546Spatrick 
78061da546Spatrick   process_sp = exe_ctx.GetProcessSP();
79061da546Spatrick   target_sp = exe_ctx.GetTargetSP();
80061da546Spatrick   frame_sp = exe_ctx.GetFrameSP();
81061da546Spatrick 
82061da546Spatrick   if (m_address.IsValid()) {
83061da546Spatrick     if (!frame_sp)
84061da546Spatrick       return false;
85061da546Spatrick     return (Address::CompareLoadAddress(m_address,
86061da546Spatrick                                         frame_sp->GetFrameCodeAddress(),
87061da546Spatrick                                         target_sp.get()) == 0);
88061da546Spatrick   }
89061da546Spatrick 
90061da546Spatrick   return true;
91061da546Spatrick }
92061da546Spatrick 
MatchesContext(ExecutionContext & exe_ctx)93061da546Spatrick bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
94061da546Spatrick   lldb::TargetSP target_sp;
95061da546Spatrick   lldb::ProcessSP process_sp;
96061da546Spatrick   lldb::StackFrameSP frame_sp;
97061da546Spatrick 
98061da546Spatrick   return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
99061da546Spatrick }
100061da546Spatrick 
GetObjectPointerValueObject(lldb::StackFrameSP frame_sp,ConstString const & object_name,Status & err)101*f6aab3d8Srobert lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject(
102*f6aab3d8Srobert     lldb::StackFrameSP frame_sp, ConstString const &object_name, Status &err) {
103061da546Spatrick   err.Clear();
104061da546Spatrick 
105061da546Spatrick   if (!frame_sp) {
106061da546Spatrick     err.SetErrorStringWithFormat(
107061da546Spatrick         "Couldn't load '%s' because the context is incomplete",
108061da546Spatrick         object_name.AsCString());
109*f6aab3d8Srobert     return {};
110061da546Spatrick   }
111061da546Spatrick 
112061da546Spatrick   lldb::VariableSP var_sp;
113061da546Spatrick   lldb::ValueObjectSP valobj_sp;
114061da546Spatrick 
115*f6aab3d8Srobert   return frame_sp->GetValueForVariableExpressionPath(
116dda28197Spatrick       object_name.GetStringRef(), lldb::eNoDynamicValues,
117061da546Spatrick       StackFrame::eExpressionPathOptionCheckPtrVsMember |
118061da546Spatrick           StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
119061da546Spatrick           StackFrame::eExpressionPathOptionsNoSyntheticChildren |
120061da546Spatrick           StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
121061da546Spatrick       var_sp, err);
122*f6aab3d8Srobert }
123*f6aab3d8Srobert 
GetObjectPointer(lldb::StackFrameSP frame_sp,ConstString & object_name,Status & err)124*f6aab3d8Srobert lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
125*f6aab3d8Srobert                                               ConstString &object_name,
126*f6aab3d8Srobert                                               Status &err) {
127*f6aab3d8Srobert   auto valobj_sp =
128*f6aab3d8Srobert       GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
129061da546Spatrick 
130061da546Spatrick   if (!err.Success() || !valobj_sp.get())
131061da546Spatrick     return LLDB_INVALID_ADDRESS;
132061da546Spatrick 
133061da546Spatrick   lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
134061da546Spatrick 
135061da546Spatrick   if (ret == LLDB_INVALID_ADDRESS) {
136061da546Spatrick     err.SetErrorStringWithFormat(
137061da546Spatrick         "Couldn't load '%s' because its value couldn't be evaluated",
138061da546Spatrick         object_name.AsCString());
139061da546Spatrick     return LLDB_INVALID_ADDRESS;
140061da546Spatrick   }
141061da546Spatrick 
142061da546Spatrick   return ret;
143061da546Spatrick }
144061da546Spatrick 
145dda28197Spatrick lldb::ExpressionResults
Evaluate(ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options,llvm::StringRef expr,llvm::StringRef prefix,lldb::ValueObjectSP & result_valobj_sp,Status & error,std::string * fixed_expression,ValueObject * ctx_obj)146dda28197Spatrick UserExpression::Evaluate(ExecutionContext &exe_ctx,
147dda28197Spatrick                          const EvaluateExpressionOptions &options,
148061da546Spatrick                          llvm::StringRef expr, llvm::StringRef prefix,
149061da546Spatrick                          lldb::ValueObjectSP &result_valobj_sp, Status &error,
150dda28197Spatrick                          std::string *fixed_expression, ValueObject *ctx_obj) {
151*f6aab3d8Srobert   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
152061da546Spatrick 
153061da546Spatrick   if (ctx_obj) {
154*f6aab3d8Srobert     static unsigned const ctx_type_mask = lldb::TypeFlags::eTypeIsClass |
155*f6aab3d8Srobert                                           lldb::TypeFlags::eTypeIsStructUnion |
156*f6aab3d8Srobert                                           lldb::TypeFlags::eTypeIsReference;
157061da546Spatrick     if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
158061da546Spatrick       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
159061da546Spatrick                     "an invalid type, can't run expressions.");
160061da546Spatrick       error.SetErrorString("a context object of an invalid type passed");
161061da546Spatrick       return lldb::eExpressionSetupError;
162061da546Spatrick     }
163061da546Spatrick   }
164061da546Spatrick 
165*f6aab3d8Srobert   if (ctx_obj && ctx_obj->GetTypeInfo() & lldb::TypeFlags::eTypeIsReference) {
166*f6aab3d8Srobert     Status error;
167*f6aab3d8Srobert     lldb::ValueObjectSP deref_ctx_sp = ctx_obj->Dereference(error);
168*f6aab3d8Srobert     if (!error.Success()) {
169*f6aab3d8Srobert       LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
170*f6aab3d8Srobert                     "a reference type that can't be dereferenced, can't run "
171*f6aab3d8Srobert                     "expressions.");
172*f6aab3d8Srobert       error.SetErrorString(
173*f6aab3d8Srobert           "passed context object of an reference type cannot be deferenced");
174*f6aab3d8Srobert       return lldb::eExpressionSetupError;
175*f6aab3d8Srobert     }
176*f6aab3d8Srobert 
177*f6aab3d8Srobert     ctx_obj = deref_ctx_sp.get();
178*f6aab3d8Srobert   }
179*f6aab3d8Srobert 
180061da546Spatrick   lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
181061da546Spatrick   lldb::LanguageType language = options.GetLanguage();
182061da546Spatrick   const ResultType desired_type = options.DoesCoerceToId()
183061da546Spatrick                                       ? UserExpression::eResultTypeId
184061da546Spatrick                                       : UserExpression::eResultTypeAny;
185061da546Spatrick   lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
186061da546Spatrick 
187061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
188061da546Spatrick   if (!target) {
189dda28197Spatrick     LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a NULL target, can't "
190061da546Spatrick                   "run expressions.");
191061da546Spatrick     error.SetErrorString("expression passed a null target");
192061da546Spatrick     return lldb::eExpressionSetupError;
193061da546Spatrick   }
194061da546Spatrick 
195061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
196061da546Spatrick 
197*f6aab3d8Srobert   if (process == nullptr && execution_policy == eExecutionPolicyAlways) {
198*f6aab3d8Srobert     LLDB_LOG(log, "== [UserExpression::Evaluate] No process, but the policy is "
199*f6aab3d8Srobert                   "eExecutionPolicyAlways");
200061da546Spatrick 
201*f6aab3d8Srobert     error.SetErrorString("expression needed to run but couldn't: no process");
202061da546Spatrick 
203061da546Spatrick     return execution_results;
204061da546Spatrick   }
205*f6aab3d8Srobert   // Since we might need to call allocate memory and maybe call code to make
206*f6aab3d8Srobert   // the caller, we need to be stopped.
207*f6aab3d8Srobert   if (process != nullptr && process->GetState() != lldb::eStateStopped) {
208*f6aab3d8Srobert     error.SetErrorString("Can't make a function caller while the process is "
209*f6aab3d8Srobert                           "running");
210*f6aab3d8Srobert     return execution_results;
211061da546Spatrick   }
212061da546Spatrick 
213*f6aab3d8Srobert 
214be691f3bSpatrick   // Explicitly force the IR interpreter to evaluate the expression when the
215be691f3bSpatrick   // there is no process that supports running the expression for us. Don't
216be691f3bSpatrick   // change the execution policy if we have the special top-level policy that
217be691f3bSpatrick   // doesn't contain any expression and there is nothing to interpret.
218be691f3bSpatrick   if (execution_policy != eExecutionPolicyTopLevel &&
219be691f3bSpatrick       (process == nullptr || !process->CanJIT()))
220061da546Spatrick     execution_policy = eExecutionPolicyNever;
221061da546Spatrick 
222061da546Spatrick   // We need to set the expression execution thread here, turns out parse can
223061da546Spatrick   // call functions in the process of looking up symbols, which will escape the
224061da546Spatrick   // context set by exe_ctx passed to Execute.
225061da546Spatrick   lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
226061da546Spatrick   ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
227061da546Spatrick       thread_sp);
228061da546Spatrick 
229061da546Spatrick   llvm::StringRef full_prefix;
230061da546Spatrick   llvm::StringRef option_prefix(options.GetPrefix());
231061da546Spatrick   std::string full_prefix_storage;
232061da546Spatrick   if (!prefix.empty() && !option_prefix.empty()) {
233dda28197Spatrick     full_prefix_storage = std::string(prefix);
234dda28197Spatrick     full_prefix_storage.append(std::string(option_prefix));
235061da546Spatrick     full_prefix = full_prefix_storage;
236061da546Spatrick   } else if (!prefix.empty())
237061da546Spatrick     full_prefix = prefix;
238061da546Spatrick   else
239061da546Spatrick     full_prefix = option_prefix;
240061da546Spatrick 
241061da546Spatrick   // If the language was not specified in the expression command, set it to the
242061da546Spatrick   // language in the target's properties if specified, else default to the
243061da546Spatrick   // langage for the frame.
244061da546Spatrick   if (language == lldb::eLanguageTypeUnknown) {
245061da546Spatrick     if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
246061da546Spatrick       language = target->GetLanguage();
247061da546Spatrick     else if (StackFrame *frame = exe_ctx.GetFramePtr())
248061da546Spatrick       language = frame->GetLanguage();
249061da546Spatrick   }
250061da546Spatrick 
251061da546Spatrick   lldb::UserExpressionSP user_expression_sp(
252061da546Spatrick       target->GetUserExpressionForLanguage(expr, full_prefix, language,
253061da546Spatrick                                            desired_type, options, ctx_obj,
254061da546Spatrick                                            error));
255061da546Spatrick   if (error.Fail()) {
256dda28197Spatrick     LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==",
257061da546Spatrick              error.AsCString());
258061da546Spatrick     return lldb::eExpressionSetupError;
259061da546Spatrick   }
260061da546Spatrick 
261dda28197Spatrick   LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==",
262dda28197Spatrick            expr.str());
263061da546Spatrick 
264061da546Spatrick   const bool keep_expression_in_memory = true;
265061da546Spatrick   const bool generate_debug_info = options.GetGenerateDebugInfo();
266061da546Spatrick 
267061da546Spatrick   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
268061da546Spatrick     error.SetErrorString("expression interrupted by callback before parse");
269061da546Spatrick     result_valobj_sp = ValueObjectConstResult::Create(
270061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), error);
271061da546Spatrick     return lldb::eExpressionInterrupted;
272061da546Spatrick   }
273061da546Spatrick 
274061da546Spatrick   DiagnosticManager diagnostic_manager;
275061da546Spatrick 
276061da546Spatrick   bool parse_success =
277061da546Spatrick       user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
278061da546Spatrick                                 keep_expression_in_memory, generate_debug_info);
279061da546Spatrick 
280061da546Spatrick   // Calculate the fixed expression always, since we need it for errors.
281061da546Spatrick   std::string tmp_fixed_expression;
282061da546Spatrick   if (fixed_expression == nullptr)
283061da546Spatrick     fixed_expression = &tmp_fixed_expression;
284061da546Spatrick 
285*f6aab3d8Srobert   *fixed_expression = user_expression_sp->GetFixedText().str();
286061da546Spatrick 
287061da546Spatrick   // If there is a fixed expression, try to parse it:
288061da546Spatrick   if (!parse_success) {
289dda28197Spatrick     // Delete the expression that failed to parse before attempting to parse
290dda28197Spatrick     // the next expression.
291dda28197Spatrick     user_expression_sp.reset();
292dda28197Spatrick 
293061da546Spatrick     execution_results = lldb::eExpressionParseError;
294*f6aab3d8Srobert     if (!fixed_expression->empty() && options.GetAutoApplyFixIts()) {
295dda28197Spatrick       const uint64_t max_fix_retries = options.GetRetriesWithFixIts();
296dda28197Spatrick       for (uint64_t i = 0; i < max_fix_retries; ++i) {
297dda28197Spatrick         // Try parsing the fixed expression.
298061da546Spatrick         lldb::UserExpressionSP fixed_expression_sp(
299dda28197Spatrick             target->GetUserExpressionForLanguage(
300dda28197Spatrick                 fixed_expression->c_str(), full_prefix, language, desired_type,
301dda28197Spatrick                 options, ctx_obj, error));
302061da546Spatrick         DiagnosticManager fixed_diagnostic_manager;
303061da546Spatrick         parse_success = fixed_expression_sp->Parse(
304061da546Spatrick             fixed_diagnostic_manager, exe_ctx, execution_policy,
305061da546Spatrick             keep_expression_in_memory, generate_debug_info);
306061da546Spatrick         if (parse_success) {
307061da546Spatrick           diagnostic_manager.Clear();
308061da546Spatrick           user_expression_sp = fixed_expression_sp;
309dda28197Spatrick           break;
310061da546Spatrick         } else {
311dda28197Spatrick           // The fixed expression also didn't parse. Let's check for any new
312dda28197Spatrick           // Fix-Its we could try.
313*f6aab3d8Srobert           if (!fixed_expression_sp->GetFixedText().empty()) {
314*f6aab3d8Srobert             *fixed_expression = fixed_expression_sp->GetFixedText().str();
315dda28197Spatrick           } else {
316dda28197Spatrick             // Fixed expression didn't compile without a fixit, don't retry and
317dda28197Spatrick             // don't tell the user about it.
318061da546Spatrick             fixed_expression->clear();
319dda28197Spatrick             break;
320dda28197Spatrick           }
321dda28197Spatrick         }
322061da546Spatrick       }
323061da546Spatrick     }
324061da546Spatrick 
325061da546Spatrick     if (!parse_success) {
326be691f3bSpatrick       std::string msg;
327be691f3bSpatrick       {
328be691f3bSpatrick         llvm::raw_string_ostream os(msg);
329be691f3bSpatrick         os << "expression failed to parse:\n";
330be691f3bSpatrick         if (!diagnostic_manager.Diagnostics().empty())
331be691f3bSpatrick           os << diagnostic_manager.GetString();
332061da546Spatrick         else
333be691f3bSpatrick           os << "unknown error";
334be691f3bSpatrick         if (target->GetEnableNotifyAboutFixIts() && fixed_expression &&
335be691f3bSpatrick             !fixed_expression->empty())
336be691f3bSpatrick           os << "\nfixed expression suggested:\n  " << *fixed_expression;
337061da546Spatrick       }
338be691f3bSpatrick       error.SetExpressionError(execution_results, msg.c_str());
339061da546Spatrick     }
340061da546Spatrick   }
341061da546Spatrick 
342061da546Spatrick   if (parse_success) {
343061da546Spatrick     lldb::ExpressionVariableSP expr_result;
344061da546Spatrick 
345061da546Spatrick     if (execution_policy == eExecutionPolicyNever &&
346061da546Spatrick         !user_expression_sp->CanInterpret()) {
347dda28197Spatrick       LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
348061da546Spatrick                     "is not constant ==");
349061da546Spatrick 
350061da546Spatrick       if (!diagnostic_manager.Diagnostics().size())
351061da546Spatrick         error.SetExpressionError(lldb::eExpressionSetupError,
352061da546Spatrick                                  "expression needed to run but couldn't");
353061da546Spatrick     } else if (execution_policy == eExecutionPolicyTopLevel) {
354061da546Spatrick       error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
355061da546Spatrick       return lldb::eExpressionCompleted;
356061da546Spatrick     } else {
357061da546Spatrick       if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
358061da546Spatrick         error.SetExpressionError(
359061da546Spatrick             lldb::eExpressionInterrupted,
360061da546Spatrick             "expression interrupted by callback before execution");
361061da546Spatrick         result_valobj_sp = ValueObjectConstResult::Create(
362061da546Spatrick             exe_ctx.GetBestExecutionContextScope(), error);
363061da546Spatrick         return lldb::eExpressionInterrupted;
364061da546Spatrick       }
365061da546Spatrick 
366061da546Spatrick       diagnostic_manager.Clear();
367061da546Spatrick 
368dda28197Spatrick       LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");
369061da546Spatrick 
370061da546Spatrick       execution_results =
371061da546Spatrick           user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
372061da546Spatrick                                       user_expression_sp, expr_result);
373061da546Spatrick 
374061da546Spatrick       if (execution_results != lldb::eExpressionCompleted) {
375dda28197Spatrick         LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
376061da546Spatrick                       "abnormally ==");
377061da546Spatrick 
378061da546Spatrick         if (!diagnostic_manager.Diagnostics().size())
379061da546Spatrick           error.SetExpressionError(
380061da546Spatrick               execution_results, "expression failed to execute, unknown error");
381061da546Spatrick         else
382061da546Spatrick           error.SetExpressionError(execution_results,
383061da546Spatrick                                    diagnostic_manager.GetString().c_str());
384061da546Spatrick       } else {
385061da546Spatrick         if (expr_result) {
386061da546Spatrick           result_valobj_sp = expr_result->GetValueObject();
387be691f3bSpatrick           result_valobj_sp->SetPreferredDisplayLanguage(language);
388061da546Spatrick 
389dda28197Spatrick           LLDB_LOG(log,
390061da546Spatrick                    "== [UserExpression::Evaluate] Execution completed "
391be691f3bSpatrick                    "normally with result {0} ==",
392061da546Spatrick                    result_valobj_sp->GetValueAsCString());
393061da546Spatrick         } else {
394dda28197Spatrick           LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
395061da546Spatrick                         "normally with no result ==");
396061da546Spatrick 
397061da546Spatrick           error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
398061da546Spatrick         }
399061da546Spatrick       }
400061da546Spatrick     }
401061da546Spatrick   }
402061da546Spatrick 
403061da546Spatrick   if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
404061da546Spatrick     error.SetExpressionError(
405061da546Spatrick         lldb::eExpressionInterrupted,
406061da546Spatrick         "expression interrupted by callback after complete");
407061da546Spatrick     return lldb::eExpressionInterrupted;
408061da546Spatrick   }
409061da546Spatrick 
410061da546Spatrick   if (result_valobj_sp.get() == nullptr) {
411061da546Spatrick     result_valobj_sp = ValueObjectConstResult::Create(
412061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), error);
413061da546Spatrick   }
414061da546Spatrick 
415061da546Spatrick   return execution_results;
416061da546Spatrick }
417061da546Spatrick 
418061da546Spatrick lldb::ExpressionResults
Execute(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options,lldb::UserExpressionSP & shared_ptr_to_me,lldb::ExpressionVariableSP & result_var)419061da546Spatrick UserExpression::Execute(DiagnosticManager &diagnostic_manager,
420061da546Spatrick                         ExecutionContext &exe_ctx,
421061da546Spatrick                         const EvaluateExpressionOptions &options,
422061da546Spatrick                         lldb::UserExpressionSP &shared_ptr_to_me,
423061da546Spatrick                         lldb::ExpressionVariableSP &result_var) {
424061da546Spatrick   lldb::ExpressionResults expr_result = DoExecute(
425061da546Spatrick       diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
426061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
427061da546Spatrick   if (options.GetResultIsInternal() && result_var && target) {
428061da546Spatrick     if (auto *persistent_state =
429061da546Spatrick             target->GetPersistentExpressionStateForLanguage(m_language))
430061da546Spatrick       persistent_state->RemovePersistentVariable(result_var);
431061da546Spatrick   }
432061da546Spatrick   return expr_result;
433061da546Spatrick }
434