diff options
Diffstat (limited to 'source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp')
-rw-r--r-- | source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp | 257 |
1 files changed, 158 insertions, 99 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 11f7f84ff5f1..52d49aecec9a 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -23,8 +23,10 @@ #include "ClangExpressionParser.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" +#include "ClangDiagnostic.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" @@ -55,28 +57,25 @@ using namespace lldb_private; -ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, - const EvaluateExpressionOptions &options) : - LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options), - m_type_system_helper(*m_target_wp.lock().get()) +ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, + const EvaluateExpressionOptions &options) + : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, options), + m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { switch (m_language) { - case lldb::eLanguageTypeC_plus_plus: - m_allow_cxx = true; - break; - case lldb::eLanguageTypeObjC: - m_allow_objc = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - default: - m_allow_cxx = true; - m_allow_objc = true; - break; + case lldb::eLanguageTypeC_plus_plus: + m_allow_cxx = true; + break; + case lldb::eLanguageTypeObjC: + m_allow_objc = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + default: + m_allow_cxx = true; + m_allow_objc = true; + break; } } @@ -326,11 +325,9 @@ ApplyObjcCastHack(std::string &expr) } bool -ClangUserExpression::Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) +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)); @@ -346,13 +343,13 @@ ClangUserExpression::Parse (Stream &error_stream, } else { - error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)"); return false; } } else { - error_stream.PutCString ("error: couldn't start parsing (no target)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)"); return false; } @@ -360,11 +357,9 @@ ClangUserExpression::Parse (Stream &error_stream, if (!err.Success()) { - error_stream.Printf("warning: %s\n", err.AsCString()); + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString()); } - StreamString m_transformed_stream; - //////////////////////////////////// // Generate the expression // @@ -404,22 +399,30 @@ ClangUserExpression::Parse (Stream &error_stream, } } } - - std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); - - lldb::LanguageType lang_type; - if (m_in_cplusplus_method) - lang_type = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - lang_type = lldb::eLanguageTypeObjC; - else - lang_type = lldb::eLanguageTypeC; + lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; - if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { - error_stream.PutCString ("error: couldn't construct expression body"); - return false; + m_transformed_text = m_expr_text; + } + else + { + std::unique_ptr<ExpressionSourceCode> source_code( + ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); + + if (m_in_cplusplus_method) + lang_type = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + lang_type = lldb::eLanguageTypeObjC; + else + lang_type = lldb::eLanguageTypeC; + + if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method, exe_ctx)) + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body"); + return false; + } } if (log) @@ -433,7 +436,7 @@ ClangUserExpression::Parse (Stream &error_stream, if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } @@ -467,26 +470,47 @@ ClangUserExpression::Parse (Stream &error_stream, if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. 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 (error_stream); + 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) { - error_stream.Printf ("error: %d errors parsing expression\n", 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, lang_type, fixed_start, fixed_end)) + m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); + } + } ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -497,16 +521,70 @@ ClangUserExpression::Parse (Stream &error_stream, // Prepare the output of the parser for execution, evaluating it statically if possible // - Error jit_error = parser.PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - m_can_interpret, - execution_policy); + { + Error 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.PutCString(eDiagnosticSeverityError, error_cstr); + else + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); + return false; + } + } + + if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) + { + Error 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.PutCString(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()); + lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { @@ -517,52 +595,23 @@ ClangUserExpression::Parse (Stream &error_stream, m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); } -// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); -// StreamFile strm (stdout, false); -// if (jit_obj_file) -// { -// jit_obj_file->GetSectionList(); -// jit_obj_file->GetSymtab(); -// jit_obj_file->Dump(&strm); -// } -// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); -// if (jit_sym_vendor) -// { -// lldb_private::SymbolContextList sc_list; -// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); -// sc_list.Dump(&strm, target); -// jit_sym_vendor->Dump(&strm); -// } } - ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. + ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any + // ClangASTImporter::Minions. - if (jit_error.Success()) - { - if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) - m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); - return true; - } - else - { - const char *error_cstr = jit_error.AsCString(); - if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); - else - error_stream.Printf ("error: expression can't be interpreted or run\n"); - return false; - } + if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) + m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + return true; } bool -ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, - std::vector<lldb::addr_t> &args, - lldb::addr_t struct_address, - Stream &error_stream) +ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, + lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) { lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; - lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; - + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + if (m_needs_object_ptr) { lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); @@ -581,7 +630,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, } else { - error_stream.Printf("Need object pointer but don't know the language\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language"); return false; } @@ -591,7 +640,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf("warning: `%s' is not accessible (subsituting 0)\n", object_name.AsCString()); object_ptr = 0; } @@ -603,12 +652,14 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityWarning, + "couldn't get cmd pointer (substituting NULL): %s", + object_ptr_error.AsCString()); cmd_ptr = 0; } } - if (object_ptr) - args.push_back(object_ptr); + + args.push_back(object_ptr); if (m_in_objectivec_method) args.push_back(cmd_ptr); @@ -635,14 +686,22 @@ ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &e } clang::ASTConsumer * -ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough) { - m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, - m_target)); + m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target)); return m_result_synthesizer_up.get(); } +void +ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() +{ + if (m_result_synthesizer_up.get()) + { + m_result_synthesizer_up->CommitPersistentDecls(); + } +} + ClangUserExpression::ResultDelegate::ResultDelegate() { } |