1151c032cSJim Ingham //===-- UserExpression.cpp ---------------------------------*- C++ -*-===// 2151c032cSJim Ingham // 3151c032cSJim Ingham // The LLVM Compiler Infrastructure 4151c032cSJim Ingham // 5151c032cSJim Ingham // This file is distributed under the University of Illinois Open Source 6151c032cSJim Ingham // License. See LICENSE.TXT for details. 7151c032cSJim Ingham // 8151c032cSJim Ingham //===----------------------------------------------------------------------===// 9151c032cSJim Ingham 10151c032cSJim Ingham #include <stdio.h> 11151c032cSJim Ingham #if HAVE_SYS_TYPES_H 12151c032cSJim Ingham #include <sys/types.h> 13151c032cSJim Ingham #endif 14151c032cSJim Ingham 15151c032cSJim Ingham #include <cstdlib> 16151c032cSJim Ingham #include <map> 17b9c1b51eSKate Stone #include <string> 18151c032cSJim Ingham 19579e70c9SSean Callanan #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" 20151c032cSJim Ingham #include "lldb/Core/Module.h" 21151c032cSJim Ingham #include "lldb/Core/StreamFile.h" 22151c032cSJim Ingham #include "lldb/Core/ValueObjectConstResult.h" 23579e70c9SSean Callanan #include "lldb/Expression/DiagnosticManager.h" 24151c032cSJim Ingham #include "lldb/Expression/ExpressionSourceCode.h" 25151c032cSJim Ingham #include "lldb/Expression/IRExecutionUnit.h" 26151c032cSJim Ingham #include "lldb/Expression/IRInterpreter.h" 27151c032cSJim Ingham #include "lldb/Expression/Materializer.h" 28151c032cSJim Ingham #include "lldb/Expression/UserExpression.h" 29151c032cSJim Ingham #include "lldb/Host/HostInfo.h" 30151c032cSJim Ingham #include "lldb/Symbol/Block.h" 31151c032cSJim Ingham #include "lldb/Symbol/Function.h" 32151c032cSJim Ingham #include "lldb/Symbol/ObjectFile.h" 33151c032cSJim Ingham #include "lldb/Symbol/SymbolVendor.h" 34151c032cSJim Ingham #include "lldb/Symbol/Type.h" 358f1f9a1bSSean Callanan #include "lldb/Symbol/TypeSystem.h" 36151c032cSJim Ingham #include "lldb/Symbol/VariableList.h" 37151c032cSJim Ingham #include "lldb/Target/ExecutionContext.h" 38151c032cSJim Ingham #include "lldb/Target/Process.h" 39151c032cSJim Ingham #include "lldb/Target/StackFrame.h" 40151c032cSJim Ingham #include "lldb/Target/Target.h" 41151c032cSJim Ingham #include "lldb/Target/ThreadPlan.h" 42151c032cSJim Ingham #include "lldb/Target/ThreadPlanCallUserExpression.h" 43bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h" 446f9e6901SZachary Turner #include "lldb/Utility/Log.h" 45bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 46151c032cSJim Ingham 47151c032cSJim Ingham using namespace lldb_private; 48151c032cSJim Ingham 4919a63fc6SJim Ingham UserExpression::UserExpression(ExecutionContextScope &exe_scope, 50c5d7df90SZachary Turner llvm::StringRef expr, llvm::StringRef prefix, 5119a63fc6SJim Ingham lldb::LanguageType language, 5219a63fc6SJim Ingham ResultType desired_type, 53b9c1b51eSKate Stone const EvaluateExpressionOptions &options) 54c5d7df90SZachary Turner : Expression(exe_scope), m_expr_text(expr), m_expr_prefix(prefix), 55c5d7df90SZachary Turner m_language(language), m_desired_type(desired_type), m_options(options) {} 56151c032cSJim Ingham 57b9c1b51eSKate Stone UserExpression::~UserExpression() {} 58151c032cSJim Ingham 59b9c1b51eSKate Stone void UserExpression::InstallContext(ExecutionContext &exe_ctx) { 60151c032cSJim Ingham m_jit_process_wp = exe_ctx.GetProcessSP(); 61151c032cSJim Ingham 62151c032cSJim Ingham lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); 63151c032cSJim Ingham 64151c032cSJim Ingham if (frame_sp) 65151c032cSJim Ingham m_address = frame_sp->GetFrameCodeAddress(); 66151c032cSJim Ingham } 67151c032cSJim Ingham 68b9c1b51eSKate Stone bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx, 69151c032cSJim Ingham lldb::TargetSP &target_sp, 70151c032cSJim Ingham lldb::ProcessSP &process_sp, 71b9c1b51eSKate Stone lldb::StackFrameSP &frame_sp) { 72151c032cSJim Ingham lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); 73151c032cSJim Ingham process_sp = exe_ctx.GetProcessSP(); 74151c032cSJim Ingham 75151c032cSJim Ingham if (process_sp != expected_process_sp) 76151c032cSJim Ingham return false; 77151c032cSJim Ingham 78151c032cSJim Ingham process_sp = exe_ctx.GetProcessSP(); 79151c032cSJim Ingham target_sp = exe_ctx.GetTargetSP(); 80151c032cSJim Ingham frame_sp = exe_ctx.GetFrameSP(); 81151c032cSJim Ingham 82b9c1b51eSKate Stone if (m_address.IsValid()) { 83151c032cSJim Ingham if (!frame_sp) 84151c032cSJim Ingham return false; 85151c032cSJim Ingham else 86b9c1b51eSKate Stone return (0 == Address::CompareLoadAddress(m_address, 87b9c1b51eSKate Stone frame_sp->GetFrameCodeAddress(), 88b9c1b51eSKate Stone target_sp.get())); 89151c032cSJim Ingham } 90151c032cSJim Ingham 91151c032cSJim Ingham return true; 92151c032cSJim Ingham } 93151c032cSJim Ingham 94b9c1b51eSKate Stone bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) { 95151c032cSJim Ingham lldb::TargetSP target_sp; 96151c032cSJim Ingham lldb::ProcessSP process_sp; 97151c032cSJim Ingham lldb::StackFrameSP frame_sp; 98151c032cSJim Ingham 99151c032cSJim Ingham return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); 100151c032cSJim Ingham } 101151c032cSJim Ingham 102b9c1b51eSKate Stone lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, 103151c032cSJim Ingham ConstString &object_name, 104*97206d57SZachary Turner Status &err) { 105151c032cSJim Ingham err.Clear(); 106151c032cSJim Ingham 107b9c1b51eSKate Stone if (!frame_sp) { 108b9c1b51eSKate Stone err.SetErrorStringWithFormat( 109b9c1b51eSKate Stone "Couldn't load '%s' because the context is incomplete", 110b9c1b51eSKate Stone object_name.AsCString()); 111151c032cSJim Ingham return LLDB_INVALID_ADDRESS; 112151c032cSJim Ingham } 113151c032cSJim Ingham 114151c032cSJim Ingham lldb::VariableSP var_sp; 115151c032cSJim Ingham lldb::ValueObjectSP valobj_sp; 116151c032cSJim Ingham 117b9c1b51eSKate Stone valobj_sp = frame_sp->GetValueForVariableExpressionPath( 118b9c1b51eSKate Stone object_name.AsCString(), lldb::eNoDynamicValues, 119151c032cSJim Ingham StackFrame::eExpressionPathOptionCheckPtrVsMember | 120151c032cSJim Ingham StackFrame::eExpressionPathOptionsNoFragileObjcIvar | 121151c032cSJim Ingham StackFrame::eExpressionPathOptionsNoSyntheticChildren | 122151c032cSJim Ingham StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, 123b9c1b51eSKate Stone var_sp, err); 124151c032cSJim Ingham 125151c032cSJim Ingham if (!err.Success() || !valobj_sp.get()) 126151c032cSJim Ingham return LLDB_INVALID_ADDRESS; 127151c032cSJim Ingham 128151c032cSJim Ingham lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 129151c032cSJim Ingham 130b9c1b51eSKate Stone if (ret == LLDB_INVALID_ADDRESS) { 131b9c1b51eSKate Stone err.SetErrorStringWithFormat( 132b9c1b51eSKate Stone "Couldn't load '%s' because its value couldn't be evaluated", 133b9c1b51eSKate Stone object_name.AsCString()); 134151c032cSJim Ingham return LLDB_INVALID_ADDRESS; 135151c032cSJim Ingham } 136151c032cSJim Ingham 137151c032cSJim Ingham return ret; 138151c032cSJim Ingham } 139151c032cSJim Ingham 140b9c1b51eSKate Stone lldb::ExpressionResults UserExpression::Evaluate( 141b9c1b51eSKate Stone ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, 142c5d7df90SZachary Turner llvm::StringRef expr, llvm::StringRef prefix, 143*97206d57SZachary Turner lldb::ValueObjectSP &result_valobj_sp, Status &error, uint32_t line_offset, 144b9c1b51eSKate Stone std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { 145b9c1b51eSKate Stone Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | 146b9c1b51eSKate Stone LIBLLDB_LOG_STEP)); 147151c032cSJim Ingham 148151c032cSJim Ingham lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); 1491bbaede5SDawn Perchik lldb::LanguageType language = options.GetLanguage(); 150b9c1b51eSKate Stone const ResultType desired_type = options.DoesCoerceToId() 151b9c1b51eSKate Stone ? UserExpression::eResultTypeId 152b9c1b51eSKate Stone : UserExpression::eResultTypeAny; 153151c032cSJim Ingham lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; 154151c032cSJim Ingham 155151c032cSJim Ingham Target *target = exe_ctx.GetTargetPtr(); 156b9c1b51eSKate Stone if (!target) { 157151c032cSJim Ingham if (log) 158b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't " 159b9c1b51eSKate Stone "run expressions."); 16002980825SJim Ingham error.SetErrorString("expression passed a null target"); 161151c032cSJim Ingham return lldb::eExpressionSetupError; 162151c032cSJim Ingham } 163151c032cSJim Ingham 164151c032cSJim Ingham Process *process = exe_ctx.GetProcessPtr(); 165151c032cSJim Ingham 166b9c1b51eSKate Stone if (process == NULL || process->GetState() != lldb::eStateStopped) { 167b9c1b51eSKate Stone if (execution_policy == eExecutionPolicyAlways) { 168151c032cSJim Ingham if (log) 169b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Expression may not run, but " 170b9c1b51eSKate Stone "is not constant =="); 171151c032cSJim Ingham 172151c032cSJim Ingham error.SetErrorString("expression needed to run but couldn't"); 173151c032cSJim Ingham 174151c032cSJim Ingham return execution_results; 175151c032cSJim Ingham } 176151c032cSJim Ingham } 177151c032cSJim Ingham 178151c032cSJim Ingham if (process == NULL || !process->CanJIT()) 179151c032cSJim Ingham execution_policy = eExecutionPolicyNever; 1806896b355SJim Ingham 181b9c1b51eSKate Stone // We need to set the expression execution thread here, turns out parse can 182b9c1b51eSKate Stone // call functions in the process of 183b9c1b51eSKate Stone // looking up symbols, which will escape the context set by exe_ctx passed to 184b9c1b51eSKate Stone // Execute. 1856896b355SJim Ingham lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); 186b9c1b51eSKate Stone ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher( 187b9c1b51eSKate Stone thread_sp); 188151c032cSJim Ingham 189c5d7df90SZachary Turner llvm::StringRef full_prefix; 190c5d7df90SZachary Turner llvm::StringRef option_prefix(options.GetPrefix()); 191151c032cSJim Ingham std::string full_prefix_storage; 192c5d7df90SZachary Turner if (!prefix.empty() && !option_prefix.empty()) { 193c5d7df90SZachary Turner full_prefix_storage = prefix; 194151c032cSJim Ingham full_prefix_storage.append(option_prefix); 195c5d7df90SZachary Turner full_prefix = full_prefix_storage; 196c5d7df90SZachary Turner } else if (!prefix.empty()) 197c5d7df90SZachary Turner full_prefix = prefix; 198151c032cSJim Ingham else 199151c032cSJim Ingham full_prefix = option_prefix; 200151c032cSJim Ingham 2011bbaede5SDawn Perchik // If the language was not specified in the expression command, 2021bbaede5SDawn Perchik // set it to the language in the target's properties if 2031bbaede5SDawn Perchik // specified, else default to the langage for the frame. 204b9c1b51eSKate Stone if (language == lldb::eLanguageTypeUnknown) { 2051bbaede5SDawn Perchik if (target->GetLanguage() != lldb::eLanguageTypeUnknown) 2061bbaede5SDawn Perchik language = target->GetLanguage(); 2071bbaede5SDawn Perchik else if (StackFrame *frame = exe_ctx.GetFramePtr()) 2081bbaede5SDawn Perchik language = frame->GetLanguage(); 2091bbaede5SDawn Perchik } 2101bbaede5SDawn Perchik 211b9c1b51eSKate Stone lldb::UserExpressionSP user_expression_sp( 212c5d7df90SZachary Turner target->GetUserExpressionForLanguage(expr, full_prefix, language, 213b9c1b51eSKate Stone desired_type, options, error)); 214b9c1b51eSKate Stone if (error.Fail()) { 215151c032cSJim Ingham if (log) 216b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==", 217b9c1b51eSKate Stone error.AsCString()); 218151c032cSJim Ingham return lldb::eExpressionSetupError; 219151c032cSJim Ingham } 220151c032cSJim Ingham 221151c032cSJim Ingham if (log) 222b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", 223c5d7df90SZachary Turner expr.str().c_str()); 224151c032cSJim Ingham 225151c032cSJim Ingham const bool keep_expression_in_memory = true; 226151c032cSJim Ingham const bool generate_debug_info = options.GetGenerateDebugInfo(); 227151c032cSJim Ingham 228b9c1b51eSKate Stone if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) { 229151c032cSJim Ingham error.SetErrorString("expression interrupted by callback before parse"); 230b9c1b51eSKate Stone result_valobj_sp = ValueObjectConstResult::Create( 231b9c1b51eSKate Stone exe_ctx.GetBestExecutionContextScope(), error); 232151c032cSJim Ingham return lldb::eExpressionInterrupted; 233151c032cSJim Ingham } 234151c032cSJim Ingham 235579e70c9SSean Callanan DiagnosticManager diagnostic_manager; 236579e70c9SSean Callanan 237b9c1b51eSKate Stone bool parse_success = 238b9c1b51eSKate Stone user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, 239b9c1b51eSKate Stone keep_expression_in_memory, generate_debug_info); 240e5ee6f04SJim Ingham 241e5ee6f04SJim Ingham // Calculate the fixed expression always, since we need it for errors. 242e5ee6f04SJim Ingham std::string tmp_fixed_expression; 243e5ee6f04SJim Ingham if (fixed_expression == nullptr) 244e5ee6f04SJim Ingham fixed_expression = &tmp_fixed_expression; 245e5ee6f04SJim Ingham 246e5ee6f04SJim Ingham const char *fixed_text = user_expression_sp->GetFixedText(); 247e5ee6f04SJim Ingham if (fixed_text != nullptr) 248e5ee6f04SJim Ingham fixed_expression->append(fixed_text); 249e5ee6f04SJim Ingham 250e5ee6f04SJim Ingham // If there is a fixed expression, try to parse it: 251b9c1b51eSKate Stone if (!parse_success) { 252151c032cSJim Ingham execution_results = lldb::eExpressionParseError; 253b9c1b51eSKate Stone if (fixed_expression && !fixed_expression->empty() && 254b9c1b51eSKate Stone options.GetAutoApplyFixIts()) { 255b9c1b51eSKate Stone lldb::UserExpressionSP fixed_expression_sp( 256b9c1b51eSKate Stone target->GetUserExpressionForLanguage(fixed_expression->c_str(), 257b9c1b51eSKate Stone full_prefix, language, 258b9c1b51eSKate Stone desired_type, options, error)); 259e5ee6f04SJim Ingham DiagnosticManager fixed_diagnostic_manager; 260b9c1b51eSKate Stone parse_success = fixed_expression_sp->Parse( 261b9c1b51eSKate Stone fixed_diagnostic_manager, exe_ctx, execution_policy, 262b9c1b51eSKate Stone keep_expression_in_memory, generate_debug_info); 263b9c1b51eSKate Stone if (parse_success) { 264e5ee6f04SJim Ingham diagnostic_manager.Clear(); 265e5ee6f04SJim Ingham user_expression_sp = fixed_expression_sp; 266b9c1b51eSKate Stone } else { 267b9c1b51eSKate Stone // If the fixed expression failed to parse, don't tell the user about, 268b9c1b51eSKate Stone // that won't help. 269b29c42f9SJim Ingham fixed_expression->clear(); 270b29c42f9SJim Ingham } 271e5ee6f04SJim Ingham } 272e5ee6f04SJim Ingham 273b9c1b51eSKate Stone if (!parse_success) { 274b9c1b51eSKate Stone if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { 275b9c1b51eSKate Stone error.SetExpressionErrorWithFormat( 276b9c1b51eSKate Stone execution_results, 277b9c1b51eSKate Stone "expression failed to parse, fixed expression suggested:\n %s", 278e5ee6f04SJim Ingham fixed_expression->c_str()); 279b9c1b51eSKate Stone } else { 280579e70c9SSean Callanan if (!diagnostic_manager.Diagnostics().size()) 281b9c1b51eSKate Stone error.SetExpressionError(execution_results, 282b9c1b51eSKate Stone "expression failed to parse, unknown error"); 283151c032cSJim Ingham else 284b9c1b51eSKate Stone error.SetExpressionError(execution_results, 285b9c1b51eSKate Stone diagnostic_manager.GetString().c_str()); 286151c032cSJim Ingham } 287e5ee6f04SJim Ingham } 288e5ee6f04SJim Ingham } 289e5ee6f04SJim Ingham 290b9c1b51eSKate Stone if (parse_success) { 291b9c1b51eSKate Stone // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module 292b9c1b51eSKate Stone // if one was created 293998c8a1cSRyan Brown if (jit_module_sp_ptr) 294998c8a1cSRyan Brown *jit_module_sp_ptr = user_expression_sp->GetJITModule(); 2956681041dSSean Callanan 296151c032cSJim Ingham lldb::ExpressionVariableSP expr_result; 297151c032cSJim Ingham 298151c032cSJim Ingham if (execution_policy == eExecutionPolicyNever && 299b9c1b51eSKate Stone !user_expression_sp->CanInterpret()) { 300151c032cSJim Ingham if (log) 301b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Expression may not run, but " 302b9c1b51eSKate Stone "is not constant =="); 303151c032cSJim Ingham 304579e70c9SSean Callanan if (!diagnostic_manager.Diagnostics().size()) 305b9c1b51eSKate Stone error.SetExpressionError(lldb::eExpressionSetupError, 306b9c1b51eSKate Stone "expression needed to run but couldn't"); 307b9c1b51eSKate Stone } else if (execution_policy == eExecutionPolicyTopLevel) { 3082ff00003SSean Callanan error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); 3092ff00003SSean Callanan return lldb::eExpressionCompleted; 310b9c1b51eSKate Stone } else { 311b9c1b51eSKate Stone if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) { 312b9c1b51eSKate Stone error.SetExpressionError( 313b9c1b51eSKate Stone lldb::eExpressionInterrupted, 314b9c1b51eSKate Stone "expression interrupted by callback before execution"); 315b9c1b51eSKate Stone result_valobj_sp = ValueObjectConstResult::Create( 316b9c1b51eSKate Stone exe_ctx.GetBestExecutionContextScope(), error); 317151c032cSJim Ingham return lldb::eExpressionInterrupted; 318151c032cSJim Ingham } 319151c032cSJim Ingham 320579e70c9SSean Callanan diagnostic_manager.Clear(); 321151c032cSJim Ingham 322151c032cSJim Ingham if (log) 323151c032cSJim Ingham log->Printf("== [UserExpression::Evaluate] Executing expression =="); 324151c032cSJim Ingham 325579e70c9SSean Callanan execution_results = 326b9c1b51eSKate Stone user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, 327b9c1b51eSKate Stone user_expression_sp, expr_result); 328151c032cSJim Ingham 329b9c1b51eSKate Stone if (execution_results != lldb::eExpressionCompleted) { 330151c032cSJim Ingham if (log) 331b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Execution completed " 332b9c1b51eSKate Stone "abnormally =="); 333151c032cSJim Ingham 334579e70c9SSean Callanan if (!diagnostic_manager.Diagnostics().size()) 335b9c1b51eSKate Stone error.SetExpressionError( 336b9c1b51eSKate Stone execution_results, "expression failed to execute, unknown error"); 337151c032cSJim Ingham else 338b9c1b51eSKate Stone error.SetExpressionError(execution_results, 339b9c1b51eSKate Stone diagnostic_manager.GetString().c_str()); 340b9c1b51eSKate Stone } else { 341b9c1b51eSKate Stone if (expr_result) { 342151c032cSJim Ingham result_valobj_sp = expr_result->GetValueObject(); 343151c032cSJim Ingham 344151c032cSJim Ingham if (log) 345b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Execution completed " 346b9c1b51eSKate Stone "normally with result %s ==", 347151c032cSJim Ingham result_valobj_sp->GetValueAsCString()); 348b9c1b51eSKate Stone } else { 349151c032cSJim Ingham if (log) 350b9c1b51eSKate Stone log->Printf("== [UserExpression::Evaluate] Execution completed " 351b9c1b51eSKate Stone "normally with no result =="); 352151c032cSJim Ingham 353151c032cSJim Ingham error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); 354151c032cSJim Ingham } 355151c032cSJim Ingham } 356151c032cSJim Ingham } 357151c032cSJim Ingham } 358151c032cSJim Ingham 359b9c1b51eSKate Stone if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { 360b9c1b51eSKate Stone error.SetExpressionError( 361b9c1b51eSKate Stone lldb::eExpressionInterrupted, 362b9c1b51eSKate Stone "expression interrupted by callback after complete"); 363151c032cSJim Ingham return lldb::eExpressionInterrupted; 364151c032cSJim Ingham } 365151c032cSJim Ingham 366b9c1b51eSKate Stone if (result_valobj_sp.get() == NULL) { 367b9c1b51eSKate Stone result_valobj_sp = ValueObjectConstResult::Create( 368b9c1b51eSKate Stone exe_ctx.GetBestExecutionContextScope(), error); 369151c032cSJim Ingham } 370151c032cSJim Ingham 371151c032cSJim Ingham return execution_results; 372151c032cSJim Ingham } 373ff7ac6a7SJim Ingham 374ff7ac6a7SJim Ingham lldb::ExpressionResults 375ff7ac6a7SJim Ingham UserExpression::Execute(DiagnosticManager &diagnostic_manager, 376ff7ac6a7SJim Ingham ExecutionContext &exe_ctx, 377ff7ac6a7SJim Ingham const EvaluateExpressionOptions &options, 378ff7ac6a7SJim Ingham lldb::UserExpressionSP &shared_ptr_to_me, 379b9c1b51eSKate Stone lldb::ExpressionVariableSP &result_var) { 380b9c1b51eSKate Stone lldb::ExpressionResults expr_result = DoExecute( 381b9c1b51eSKate Stone diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); 382ff7ac6a7SJim Ingham Target *target = exe_ctx.GetTargetPtr(); 383b9c1b51eSKate Stone if (options.GetResultIsInternal() && result_var && target) { 384b9c1b51eSKate Stone target->GetPersistentExpressionStateForLanguage(m_language) 385b9c1b51eSKate Stone ->RemovePersistentVariable(result_var); 386ff7ac6a7SJim Ingham } 387ff7ac6a7SJim Ingham return expr_result; 388ff7ac6a7SJim Ingham } 389