bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (!PrepareForParsing(diagnostic_manager, exe_ctx)) return false; if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target"); return false; } ////////////////////////// // Parse the expression // m_materializer_ap.reset(new Materializer()); ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); OnExit on_exit([this]() { ResetDeclMap(); }); if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); return false; } if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { DeclMap()->SetLookupsEnabled(true); } Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); // We use a shared pointer here so we can use the original parser - if it // succeeds or the rewrite parser we might make if it fails. But the // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info); unsigned num_errors = parser.Parse(diagnostic_manager); // Check here for FixItHints. If there are any try to apply the fixits and // set the fixed text in m_fixed_text before returning an error. if (num_errors) { if (diagnostic_manager.HasFixIts()) { if (parser.RewriteExpression(diagnostic_manager)) { size_t fixed_start; size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); if (ExpressionSourceCode::GetOriginalBodyBounds( fixed_expression, m_expr_lang, fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); } } return false; } ////////////////////////////////////////////////////////////////////////////////////////// // Prepare the output of the parser for execution, evaluating it statically // if possible // { Status jit_error = parser.PrepareForExecution( m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, m_can_interpret, execution_policy); if (!jit_error.Success()) { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr); else diagnostic_manager.PutString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return false; } } if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) { Status static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); if (!static_init_error.Success()) { const char *error_cstr = static_init_error.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n", error_cstr); else diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't run static initializers\n"); return false; } } if (m_execution_unit_sp) { bool register_execution_unit = false; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { register_execution_unit = true; } // If there is more than one external function in the execution unit, it // needs to keep living even if it's not top level, because the result // could refer to that function. if (m_execution_unit_sp->GetJittedFunctions().size() > 1) { register_execution_unit = true; } if (register_execution_unit) { llvm::cast<PersistentExpressionState>( exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( m_language)) ->RegisterExecutionUnit(m_execution_unit_sp); } } if (generate_debug_info) { lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; jit_file.GetFilename() = const_func_name; jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); } } if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; }