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