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; +} + +  | 
