diff options
Diffstat (limited to 'source/Expression/UserExpression.cpp')
-rw-r--r-- | source/Expression/UserExpression.cpp | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp index 70f004ba25c9..3e2e07e9cb22 100644 --- a/source/Expression/UserExpression.cpp +++ b/source/Expression/UserExpression.cpp @@ -16,18 +16,19 @@ #include <string> #include <map> +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" #include "lldb/Expression/UserExpression.h" -#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" @@ -159,6 +160,7 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, + std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -193,6 +195,11 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; + + // We need to set the expression execution thread here, turns out parse can call functions in the process of + // looking up symbols, which will escape the context set by exe_ctx passed to Execute. + lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); + ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp); const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); @@ -232,8 +239,6 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } - - StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); @@ -244,23 +249,75 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } - if (!user_expression_sp->Parse (error_stream, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info)) + DiagnosticManager diagnostic_manager; + + bool parse_success = user_expression_sp->Parse(diagnostic_manager, + exe_ctx, + execution_policy, + keep_expression_in_memory, + generate_debug_info); + + // Calculate the fixed expression always, since we need it for errors. + std::string tmp_fixed_expression; + if (fixed_expression == nullptr) + fixed_expression = &tmp_fixed_expression; + + const char *fixed_text = user_expression_sp->GetFixedText(); + if (fixed_text != nullptr) + fixed_expression->append(fixed_text); + + // If there is a fixed expression, try to parse it: + if (!parse_success) { execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) + { + lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(), + full_prefix, + language, + desired_type, + options, + error)); + DiagnosticManager fixed_diagnostic_manager; + parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager, + exe_ctx, + execution_policy, + keep_expression_in_memory, + generate_debug_info); + if (parse_success) + { + diagnostic_manager.Clear(); + user_expression_sp = fixed_expression_sp; + } + else + { + // If the fixed expression failed to parse, don't tell the user about, that won't help. + fixed_expression->clear(); + } + } + + if (!parse_success) + { + if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) + { + error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s", + fixed_expression->c_str()); + } + else + { + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); + else + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); + } + } } - else + + if (parse_success) { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) @@ -274,8 +331,13 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); + } + else if (execution_policy == eExecutionPolicyTopLevel) + { + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); + return lldb::eExpressionCompleted; } else { @@ -286,31 +348,23 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, return lldb::eExpressionInterrupted; } - error_stream.GetString().clear(); + diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); - execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - options, - user_expression_sp, - expr_result); - - if (options.GetResultIsInternal() && expr_result && process) - { - process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); - } + execution_results = + user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { @@ -346,3 +400,21 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, return execution_results; } + +lldb::ExpressionResults +UserExpression::Execute(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result_var) +{ + lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); + Target *target = exe_ctx.GetTargetPtr(); + if (options.GetResultIsInternal() && result_var && target) + { + target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var); + } + return expr_result; +} + + |