Index: include/lldb/Expression/DiagnosticManager.h =================================================================== --- include/lldb/Expression/DiagnosticManager.h +++ include/lldb/Expression/DiagnosticManager.h @@ -0,0 +1,90 @@ +//===-- DiagnosticManager.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef lldb_DiagnosticManager_h +#define lldb_DiagnosticManager_h + +#include "lldb/lldb-types.h" + +#include +#include + +namespace lldb_private +{ + +enum DiagnosticSeverity +{ + eDiagnosticSeverityError, + eDiagnosticSeverityWarning, + eDiagnosticSeverityRemark +}; + +const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX; + +struct Diagnostic +{ + std::string message; + uint32_t compiler_id; // Compiler-specific diagnostic ID + DiagnosticSeverity severity; +}; + +typedef std::vector DiagnosticList; + +class DiagnosticManager +{ +public: + size_t GetNumDiagnostics() + { + return m_diagnostics.size(); + } + + void ClearDiagnosticsAfter(size_t index) + { + if (index < m_diagnostics.size()) + m_diagnostics.resize(index); + } + + void Clear() + { + ClearDiagnosticsAfter(0); + } + + void GetAllDiagnosticsAfter(size_t index, DiagnosticList &list); + + void AppendDiagnostics(DiagnosticList &list); + + void AddDiagnostic(const char *message, + DiagnosticSeverity severity = eDiagnosticSeverityError, + uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) + { + m_diagnostics.push_back({std::string(message), compiler_id, severity}); + } + + size_t Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + size_t PutCString (const char *cstr); + + void AppendMessageToDiagnostic(const char *cstr) + { + if (m_diagnostics.size()) + { + m_diagnostics.back().message.push_back('\n'); + m_diagnostics.back().message.append(cstr); + } + } + + void Dump(Log *log); + std::string GetString(); +private: + DiagnosticList m_diagnostics; +}; + +} + +#endif /* lldb_DiagnosticManager_h */ Index: include/lldb/Expression/ExpressionParser.h =================================================================== --- include/lldb/Expression/ExpressionParser.h +++ include/lldb/Expression/ExpressionParser.h @@ -57,7 +57,7 @@ /// Parse a single expression and convert it to IR using Clang. Don't /// wrap the expression in anything at all. /// - /// @param[in] stream + /// @param[in] diagnostic_manager /// The stream to print errors to. /// /// @return @@ -65,7 +65,7 @@ /// success. //------------------------------------------------------------------ virtual unsigned - Parse (Stream &stream) = 0; + Parse (DiagnosticManager &diagnostic_manager) = 0; //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly Index: include/lldb/Expression/FunctionCaller.h =================================================================== --- include/lldb/Expression/FunctionCaller.h +++ include/lldb/Expression/FunctionCaller.h @@ -99,14 +99,14 @@ //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ virtual unsigned - CompileFunction (Stream &errors) = 0; + CompileFunction (DiagnosticManager &diagnostic_manager) = 0; //------------------------------------------------------------------ /// Insert the default function wrapper and its default argument struct @@ -120,8 +120,8 @@ /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. @@ -129,7 +129,7 @@ bool InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, - Stream &errors); + DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Insert the default function wrapper (using the JIT) @@ -138,14 +138,14 @@ /// The execution context to insert the function and its arguments /// into. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ bool WriteFunctionWrapper (ExecutionContext &exe_ctx, - Stream &errors); + DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Insert the default function argument struct @@ -159,15 +159,15 @@ /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ bool WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, - Stream &errors); + DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Insert an argument struct with a non-default function address and @@ -185,8 +185,8 @@ /// @param[in] arg_values /// The values of the function's arguments. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. @@ -194,7 +194,7 @@ bool WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, - Stream &errors); + DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Run the function this FunctionCaller was created with. @@ -211,8 +211,8 @@ /// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS, /// this should point to an already allocated structure with the values already written. /// - /// @param[in] errors - /// Errors will be written here if there are any. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @param[in] options /// The options for this expression execution. @@ -227,7 +227,7 @@ ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, - Stream &errors, + DiagnosticManager &diagnostic_manager, Value &results); //------------------------------------------------------------------ @@ -243,8 +243,8 @@ /// @param[in] args_addr /// The address of the argument struct. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @param[in] stop_others /// True if other threads should pause during execution. @@ -259,7 +259,7 @@ GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, - Stream &errors); + DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Get the result of the function from its struct Index: include/lldb/Expression/IRDynamicChecks.h =================================================================== --- include/lldb/Expression/IRDynamicChecks.h +++ include/lldb/Expression/IRDynamicChecks.h @@ -61,8 +61,8 @@ /// Install the utility functions into a process. This binds the /// instance of DynamicCheckerFunctions to that process. /// - /// @param[in] error_stream - /// A stream to print errors on. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to install the functions into. @@ -71,7 +71,7 @@ /// True on success; false on failure, or if the functions have /// already been installed. //------------------------------------------------------------------ - bool Install (Stream &error_stream, + bool Install (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message); Index: include/lldb/Expression/LLVMUserExpression.h =================================================================== --- include/lldb/Expression/LLVMUserExpression.h +++ include/lldb/Expression/LLVMUserExpression.h @@ -43,13 +43,13 @@ const EvaluateExpressionOptions &options); ~LLVMUserExpression() override; - lldb::ExpressionResults Execute(Stream &error_stream, + lldb::ExpressionResults Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) override; - bool FinalizeJITExecution(Stream &error_stream, + bool FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, @@ -76,15 +76,14 @@ protected: virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; - bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address); + bool PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::addr_t &struct_address); virtual bool AddArguments (ExecutionContext &exe_ctx, std::vector &args, lldb::addr_t struct_address, - Stream &error_stream) = 0; + DiagnosticManager &diagnostic_manager) = 0; - lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame. lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame. Index: include/lldb/Expression/UserExpression.h =================================================================== --- include/lldb/Expression/UserExpression.h +++ include/lldb/Expression/UserExpression.h @@ -79,8 +79,8 @@ //------------------------------------------------------------------ /// Parse the expression /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -98,7 +98,7 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ virtual bool - Parse (Stream &error_stream, + Parse (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, @@ -112,8 +112,8 @@ //------------------------------------------------------------------ /// Execute the parsed expression /// - /// @param[in] error_stream - /// A stream to print errors to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -136,7 +136,7 @@ /// @return /// A Process::Execution results value. //------------------------------------------------------------------ - virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx, + virtual lldb::ExpressionResults Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) = 0; @@ -144,8 +144,8 @@ //------------------------------------------------------------------ /// Apply the side effects of the function to program state. /// - /// @param[in] error_stream - /// A stream to print errors to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -164,7 +164,7 @@ /// @return /// A Process::Execution results value. //------------------------------------------------------------------ - virtual bool FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, + virtual bool FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0; Index: include/lldb/Expression/UtilityFunction.h =================================================================== --- include/lldb/Expression/UtilityFunction.h +++ include/lldb/Expression/UtilityFunction.h @@ -54,8 +54,8 @@ //------------------------------------------------------------------ /// Install the utility function into a process /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. @@ -64,7 +64,7 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ virtual bool - Install (Stream &error_stream, ExecutionContext &exe_ctx) = 0; + Install (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) = 0; //------------------------------------------------------------------ /// Check whether the given PC is inside the function Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -1892,7 +1892,7 @@ RunThreadPlan (ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, const EvaluateExpressionOptions &options, - Stream &errors); + DiagnosticManager &diagnostic_manager); static const char * ExecutionResultAsCString (lldb::ExpressionResults result); Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -79,6 +79,7 @@ class DataExtractor; class Debugger; class Declaration; +class DiagnosticManager; class Disassembler; class DumpValueObjectOptions; class DynamicCheckerFunctions; Index: packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py +++ packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py @@ -36,9 +36,9 @@ # Print non-existant variable self.runCmd("-var-create var1 * undef") - self.expect("\^error,msg=\"error: error: use of undeclared identifier \'undef\'\\\\nerror: 1 errors parsing expression\\\\n\"") + self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\nerror: 1 error parsing expression\\\\n\"") self.runCmd("-data-evaluate-expression undef") - self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\nerror: 1 errors parsing expression\\\\n\"") + self.expect("\^error,msg=\"use of undeclared identifier \'undef\'\\\\nerror: 1 error parsing expression\\\\n\"") # Print global "g_MyVar", modify, delete and create again self.runCmd("-data-evaluate-expression g_MyVar") Index: source/Breakpoint/BreakpointLocation.cpp =================================================================== --- source/Breakpoint/BreakpointLocation.cpp +++ source/Breakpoint/BreakpointLocation.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/CompileUnit.h" @@ -278,6 +279,8 @@ return false; } + DiagnosticManager diagnostics; + if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) @@ -302,17 +305,15 @@ m_user_expression_sp.reset(); return true; } - - StreamString errors; - if (!m_user_expression_sp->Parse(errors, + if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s", - errors.GetData()); + diagnostics.GetString().c_str()); m_user_expression_sp.reset(); return false; } @@ -332,12 +333,12 @@ Error expr_error; - StreamString execution_errors; - + diagnostics.Clear(); + ExpressionVariableSP result_variable_sp; ExpressionResults result_code = - m_user_expression_sp->Execute(execution_errors, + m_user_expression_sp->Execute(diagnostics, exe_ctx, options, m_user_expression_sp, @@ -382,7 +383,7 @@ else { ret = false; - error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData()); + error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); } return ret; Index: source/Expression/DiagnosticManager.cpp =================================================================== --- source/Expression/DiagnosticManager.cpp +++ source/Expression/DiagnosticManager.cpp @@ -0,0 +1,88 @@ +//===-- DiagnosticManager.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/DiagnosticManager.h" + +using namespace lldb_private; + +void +DiagnosticManager::GetAllDiagnosticsAfter(size_t index, + DiagnosticList &list) +{ + if (index < m_diagnostics.size()) + { + list.resize(m_diagnostics.size() - index); + std::copy(m_diagnostics.begin() + index, m_diagnostics.end(), list.begin()); + m_diagnostics.resize(index); + } + else + { + list.clear(); + } +} + +void +DiagnosticManager::AppendDiagnostics(DiagnosticList &list) +{ + size_t index = m_diagnostics.size(); + m_diagnostics.resize(index + list.size()); + std::copy(list.begin(), list.end(), m_diagnostics.begin() + index); +} + +void +DiagnosticManager::Dump(Log *log) +{ + if (!log) + return; + + for (Diagnostic &diagnostic : m_diagnostics) + { + log->PutCString(diagnostic.message.c_str()); + } +} + +std::string +DiagnosticManager::GetString() +{ + std::string ret; + + for (Diagnostic &diagnostic : m_diagnostics) + { + ret.append(diagnostic.message); + ret.push_back('\n'); + } + + return ret; +} + +size_t +DiagnosticManager::Printf (const char *format, ...) +{ + StreamString ss; + + va_list args; + va_start (args, format); + size_t result = ss.PrintfVarArg(format, args); + va_end (args); + + AddDiagnostic(ss.GetData()); + + return result; +} + +size_t +DiagnosticManager::PutCString(const char *cstr) +{ + if (!cstr) + return 0; + AddDiagnostic(cstr); + return strlen(cstr); +} Index: source/Expression/FunctionCaller.cpp =================================================================== --- source/Expression/FunctionCaller.cpp +++ source/Expression/FunctionCaller.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -80,7 +81,7 @@ } bool -FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) +FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { Process *process = exe_ctx.GetProcessPtr(); @@ -133,9 +134,9 @@ } bool -FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager) { - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors); + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager); } // FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. @@ -144,13 +145,13 @@ FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, - Stream &errors) + DiagnosticManager &diagnostic_manager) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { - errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); + diagnostic_manager.AddDiagnostic("error: Argument information was not correctly parsed, so the function cannot be called."); return false; } @@ -195,7 +196,7 @@ size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { - errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); + diagnostic_manager.Printf("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } @@ -225,13 +226,13 @@ } bool -FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager) { - if (CompileFunction(errors) != 0) + if (CompileFunction(diagnostic_manager) != 0) return false; - if (!WriteFunctionWrapper(exe_ctx, errors)) + if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) return false; - if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors)) + if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager)) return false; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); @@ -245,7 +246,7 @@ FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, - Stream &errors) + DiagnosticManager &diagnostic_manager) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -256,7 +257,7 @@ Thread *thread = exe_ctx.GetThreadPtr(); if (thread == NULL) { - errors.Printf("Can't call a function without a valid thread."); + diagnostic_manager.PutCString("Can't call a function without a valid thread."); return NULL; } @@ -326,7 +327,7 @@ ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, - Stream &errors, + DiagnosticManager &diagnostic_manager, Value &results) { lldb::ExpressionResults return_value = lldb::eExpressionSetupError; @@ -345,12 +346,12 @@ else args_addr = LLDB_INVALID_ADDRESS; - if (CompileFunction(errors) != 0) + if (CompileFunction(diagnostic_manager) != 0) return lldb::eExpressionSetupError; if (args_addr == LLDB_INVALID_ADDRESS) { - if (!InsertFunction(exe_ctx, args_addr, errors)) + if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager)) return lldb::eExpressionSetupError; } @@ -362,7 +363,7 @@ lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, args_addr, real_options, - errors); + diagnostic_manager); if (!call_plan_sp) return lldb::eExpressionSetupError; @@ -374,7 +375,7 @@ return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, real_options, - errors); + diagnostic_manager); if (log) { Index: source/Expression/IRDynamicChecks.cpp =================================================================== --- source/Expression/IRDynamicChecks.cpp +++ source/Expression/IRDynamicChecks.cpp @@ -50,7 +50,7 @@ DynamicCheckerFunctions::~DynamicCheckerFunctions() = default; bool -DynamicCheckerFunctions::Install(Stream &error_stream, +DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { Error error; @@ -61,7 +61,7 @@ if (error.Fail()) return false; - if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) + if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) return false; Process *process = exe_ctx.GetProcessPtr(); @@ -74,7 +74,7 @@ { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); - if (!m_objc_object_check->Install(error_stream, exe_ctx)) + if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) return false; } } Index: source/Expression/IRInterpreter.cpp =================================================================== --- source/Expression/IRInterpreter.cpp +++ source/Expression/IRInterpreter.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRMemoryMap.h" #include "lldb/Expression/IRInterpreter.h" @@ -1596,7 +1597,7 @@ } lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); - lldb_private::StreamString error_stream; + lldb_private::DiagnosticManager diagnostics; lldb_private::EvaluateExpressionOptions options; // We generally receive a function pointer which we must dereference @@ -1715,7 +1716,8 @@ ); // Check if the plan is valid - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + lldb_private::StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong()); @@ -1725,7 +1727,7 @@ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); // Execute the actual function call thread plan - lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); // Check that the thread plan completed successfully if (res != lldb::ExpressionResults::eExpressionCompleted) Index: source/Expression/LLVMUserExpression.cpp =================================================================== --- source/Expression/LLVMUserExpression.cpp +++ source/Expression/LLVMUserExpression.cpp @@ -18,6 +18,7 @@ #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" @@ -76,7 +77,7 @@ } lldb::ExpressionResults -LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, +LLVMUserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { // The expression log is quite verbose, and if you're just tracking the execution of the @@ -87,9 +88,9 @@ { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address)) + if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address)) { - error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); + diagnostic_manager.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -103,7 +104,7 @@ if (!module || !function) { - error_stream.Printf("Supposed to interpret, but nothing is there"); + diagnostic_manager.PutCString("Supposed to interpret, but nothing is there"); return lldb::eExpressionSetupError; } @@ -111,9 +112,9 @@ std::vector args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -125,7 +126,7 @@ if (!interpreter_error.Success()) { - error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); + diagnostic_manager.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); return lldb::eExpressionDiscarded; } } @@ -133,7 +134,7 @@ { if (!exe_ctx.HasThreadScope()) { - error_stream.Printf("UserExpression::Execute called with no thread selected."); + diagnostic_manager.Printf("UserExpression::Execute called with no thread selected."); return lldb::eExpressionSetupError; } @@ -141,18 +142,22 @@ std::vector args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); return lldb::eExpressionSetupError; } lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address, args, options, shared_ptr_to_me)); - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) + { + diagnostic_manager.PutCString(ss.GetData()); return lldb::eExpressionSetupError; - + } + ThreadPlanCallUserExpression *user_expression_plan = static_cast(call_plan_sp.get()); @@ -168,7 +173,7 @@ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); lldb::ExpressionResults execution_result = - exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); @@ -187,20 +192,20 @@ error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) - error_stream.Printf("Execution was interrupted, reason: %s.", error_desc); + diagnostic_manager.Printf("Execution was interrupted, reason: %s.", error_desc); else - error_stream.PutCString("Execution was interrupted."); + diagnostic_manager.PutCString("Execution was interrupted."); if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) - error_stream.PutCString( - "\nThe process has been returned to the state before expression evaluation."); + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been returned to the state before expression evaluation."); else { if (execution_result == lldb::eExpressionHitBreakpoint) user_expression_plan->TransferExpressionOwnership(); - error_stream.PutCString( - "\nThe process has been left at the point where it was interrupted, " + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been left at the point where it was interrupted, " "use \"thread return -x\" to return to the state before expression evaluation."); } @@ -208,7 +213,7 @@ } else if (execution_result == lldb::eExpressionStoppedForDebug) { - error_stream.PutCString( + diagnostic_manager.PutCString( "Execution was halted at the first instruction of the expression " "function because \"debug\" was requested.\n" "Use \"thread return -x\" to return to the state before expression evaluation."); @@ -216,13 +221,13 @@ } else if (execution_result != lldb::eExpressionCompleted) { - error_stream.Printf("Couldn't execute function; result was %s\n", - Process::ExecutionResultAsCString(execution_result)); + diagnostic_manager.Printf("Couldn't execute function; result was %s", + Process::ExecutionResultAsCString(execution_result)); return execution_result; } } - if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) + if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top)) { return lldb::eExpressionCompleted; } @@ -233,13 +238,13 @@ } else { - error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); + diagnostic_manager.PutCString("Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } } bool -LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, lldb::addr_t function_stack_top) { @@ -250,7 +255,7 @@ if (!m_dematerializer_sp) { - error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present"); + diagnostic_manager.Printf("Couldn't apply expression side effects : no dematerializer is present"); return false; } @@ -260,8 +265,8 @@ if (!dematerialize_error.Success()) { - error_stream.Printf("Couldn't apply expression side effects : %s\n", - dematerialize_error.AsCString("unknown error")); + diagnostic_manager.Printf("Couldn't apply expression side effects : %s", + dematerialize_error.AsCString("unknown error")); return false; } @@ -276,7 +281,7 @@ } bool -LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::addr_t &struct_address) { lldb::TargetSP target; @@ -285,7 +290,7 @@ if (!LockAndCheckContext(exe_ctx, target, process, frame)) { - error_stream.Printf("The context has changed before we could JIT the expression!\n"); + diagnostic_manager.PutCString("The context has changed before we could JIT the expression!"); return false; } @@ -309,7 +314,7 @@ if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf("Couldn't allocate space for materialized struct: %s", alloc_error.AsCString()); return false; } } @@ -335,7 +340,7 @@ if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf("Couldn't allocate space for the stack frame: %s", alloc_error.AsCString()); return false; } } @@ -347,7 +352,7 @@ if (!materialize_error.Success()) { - error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + diagnostic_manager.Printf("Couldn't materialize: %s", materialize_error.AsCString()); return false; } } Index: source/Expression/UserExpression.cpp =================================================================== --- source/Expression/UserExpression.cpp +++ source/Expression/UserExpression.cpp @@ -22,6 +22,7 @@ #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" @@ -233,8 +234,6 @@ return lldb::eExpressionSetupError; } - StreamString error_stream; - if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); @@ -247,18 +246,20 @@ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } + + DiagnosticManager diagnostic_manager; - if (!user_expression_sp->Parse (error_stream, + if (!user_expression_sp->Parse (diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info)) { execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) + if (!diagnostic_manager.GetNumDiagnostics()) error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + error.SetExpressionError (execution_results, diagnostic_manager.GetString().c_str()); } else { @@ -274,7 +275,7 @@ if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); - if (error_stream.GetString().empty()) + if (!diagnostic_manager.GetNumDiagnostics()) error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else @@ -286,12 +287,12 @@ 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, + execution_results = user_expression_sp->Execute (diagnostic_manager, exe_ctx, options, user_expression_sp, @@ -307,10 +308,10 @@ if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); - if (error_stream.GetString().empty()) + if (!diagnostic_manager.GetNumDiagnostics()) 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 { Index: source/Expression/UtilityFunction.cpp =================================================================== --- source/Expression/UtilityFunction.cpp +++ source/Expression/UtilityFunction.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Expression/ExpressionSourceCode.h" @@ -96,26 +97,26 @@ } if (m_caller_up) { - StreamString errors; - errors.Clear(); - unsigned num_errors = m_caller_up->CompileFunction(errors); + DiagnosticManager diagnostics; + + unsigned num_errors = m_caller_up->CompileFunction(diagnostics); if (num_errors) { error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".", m_function_name.c_str(), - errors.GetData()); + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } - errors.Clear(); + diagnostics.Clear(); ExecutionContext exe_ctx(process_sp); - if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors)) + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) { error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(), - errors.GetData()); + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } Index: source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -14,6 +14,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/Error.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionParser.h" #include @@ -63,15 +64,15 @@ /// Parse a single expression and convert it to IR using Clang. Don't /// wrap the expression in anything at all. /// - /// @param[in] stream - /// The stream to print errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// The number of errors encountered during parsing. 0 means /// success. //------------------------------------------------------------------ unsigned - Parse (Stream &stream) override; + Parse (DiagnosticManager &diagnostic_manager) override; //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly Index: source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -11,7 +11,9 @@ // C++ Includes // Other libraries and framework includes #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" @@ -78,6 +80,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Language.h" +#include "lldb/Utility/LLDBAssert.h" using namespace clang; using namespace llvm; @@ -141,6 +144,75 @@ } }; +class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer +{ +public: + ClangDiagnosticManagerAdapter () : + m_passthrough(new clang::TextDiagnosticBuffer) + { + } + + ClangDiagnosticManagerAdapter (const std::shared_ptr &passthrough) : + m_passthrough(passthrough) + { + } + + void ResetManager(DiagnosticManager *manager = nullptr) + { + m_manager = manager; + } + + void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) + { + if (m_manager) + { + llvm::SmallVector diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *data = diag_str.data(); + + switch (DiagLevel) + { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + m_manager->AddDiagnostic(data); + break; + case DiagnosticsEngine::Level::Warning: + m_manager->AddDiagnostic(data, eDiagnosticSeverityWarning, Info.getID()); + break; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + m_manager->AddDiagnostic(data, eDiagnosticSeverityRemark, Info.getID()); + break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(data); + } + } + + lldbassert(Info.getID() != clang::diag::err_unsupported_ast_node && "'log enable lldb expr' to investigate."); + + m_passthrough->HandleDiagnostic(DiagLevel, Info); + } + + void FlushDiagnostics (DiagnosticsEngine &Diags) + { + m_passthrough->FlushDiagnostics(Diags); + } + + DiagnosticConsumer *clone (DiagnosticsEngine &Diags) const + { + return new ClangDiagnosticManagerAdapter (m_passthrough); + } + + clang::TextDiagnosticBuffer *GetPassthrough() + { + return m_passthrough.get(); + } +private: + DiagnosticManager *m_manager = nullptr; + std::shared_ptr m_passthrough; +}; + //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// @@ -371,7 +443,7 @@ // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); // 7. Set up the source management objects inside the compiler @@ -435,10 +507,13 @@ } unsigned -ClangExpressionParser::Parse(Stream &stream) +ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { - TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); + ClangDiagnosticManagerAdapter *adapter = static_cast(m_compiler->getDiagnostics().getClient()); + clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + + adapter->ResetManager(&diagnostic_manager); const char *expr_text = m_expr.Text(); @@ -511,29 +586,19 @@ if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; - stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + diagnostic_manager.Printf("error while importing modules: %s", m_pp_callbacks->getErrorString().c_str()); } - for (TextDiagnosticBuffer::const_iterator warn = diag_buf->warn_begin(), warn_end = diag_buf->warn_end(); - warn != warn_end; ++warn) - stream.Printf("warning: %s\n", warn->second.c_str()); - - for (TextDiagnosticBuffer::const_iterator err = diag_buf->err_begin(), err_end = diag_buf->err_end(); - err != err_end; ++err) - stream.Printf("error: %s\n", err->second.c_str()); - - for (TextDiagnosticBuffer::const_iterator note = diag_buf->note_begin(), note_end = diag_buf->note_end(); - note != note_end; ++note) - stream.Printf("note: %s\n", note->second.c_str()); - if (!num_errors) { if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { - stream.Printf("error: Couldn't infer the type of a variable\n"); + diagnostic_manager.Printf("error: Couldn't infer the type of a variable"); num_errors++; } } + + adapter->ResetManager(); return num_errors; } @@ -663,14 +728,14 @@ { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - StreamString install_errors; + DiagnosticManager install_diagnostics; - if (!dynamic_checkers->Install(install_errors, exe_ctx)) + if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { - if (install_errors.GetString().empty()) + if (install_diagnostics.GetNumDiagnostics()) err.SetErrorString ("couldn't install checkers, unknown error"); else - err.SetErrorString (install_errors.GetString().c_str()); + err.SetErrorString (install_diagnostics.GetString().c_str()); return err; } Index: source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -137,14 +137,14 @@ //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ unsigned - CompileFunction (Stream &errors) override; + CompileFunction (DiagnosticManager &diagnostic_manager) override; ExpressionTypeSystemHelper * GetTypeSystemHelper () override Index: source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -74,7 +74,7 @@ } unsigned -ClangFunctionCaller::CompileFunction (Stream &errors) +ClangFunctionCaller::CompileFunction (DiagnosticManager &diagnostic_manager) { if (m_compiled) return 0; @@ -144,7 +144,7 @@ } else { - errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + diagnostic_manager.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); return 1; } } @@ -196,11 +196,11 @@ const bool generate_debug_info = true; m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); - num_errors = m_parser->Parse (errors); + num_errors = m_parser->Parse (diagnostic_manager); } else { - errors.Printf("no process - unable to inject function"); + diagnostic_manager.PutCString("no process - unable to inject function"); num_errors = 1; } Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -126,8 +126,8 @@ //------------------------------------------------------------------ /// Parse the expression /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -145,7 +145,7 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool - Parse (Stream &error_stream, + Parse (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, @@ -191,7 +191,7 @@ AddArguments (ExecutionContext &exe_ctx, std::vector &args, lldb::addr_t struct_address, - Stream &error_stream) override; + DiagnosticManager &diagnostic_manager) override; ClangUserExpressionHelper m_type_system_helper; Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -326,7 +326,7 @@ } bool -ClangUserExpression::Parse (Stream &error_stream, +ClangUserExpression::Parse (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, @@ -346,13 +346,13 @@ } else { - error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + diagnostic_manager.PutCString ("error: couldn't start parsing (no persistent data)"); return false; } } else { - error_stream.PutCString ("error: couldn't start parsing (no target)"); + diagnostic_manager.PutCString ("error: couldn't start parsing (no target)"); return false; } @@ -360,7 +360,9 @@ if (!err.Success()) { - error_stream.Printf("warning: %s\n", err.AsCString()); + StreamString ss; + ss.Printf("warning: %s", err.AsCString()); + diagnostic_manager.AddDiagnostic(ss.GetData(), eDiagnosticSeverityWarning); } StreamString m_transformed_stream; @@ -418,7 +420,7 @@ if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) { - error_stream.PutCString ("error: couldn't construct expression body"); + diagnostic_manager.PutCString ("error: couldn't construct expression body"); return false; } @@ -433,7 +435,7 @@ if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString ("error: invalid target"); return false; } @@ -467,7 +469,7 @@ 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 ("error: current process state is unsuitable for expression parsing"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -482,11 +484,13 @@ ClangExpressionParser parser(exe_scope, *this, generate_debug_info); - unsigned num_errors = parser.Parse (error_stream); + unsigned num_errors = parser.Parse (diagnostic_manager); if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + diagnostic_manager.Printf ("error: %d error%s parsing expression", + num_errors, + num_errors == 1 ? "" : "s"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -547,9 +551,9 @@ { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); + diagnostic_manager.Printf ("error: %s", error_cstr); else - error_stream.Printf ("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf ("error: expression can't be interpreted or run"); return false; } } @@ -558,7 +562,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, std::vector &args, lldb::addr_t struct_address, - Stream &error_stream) + DiagnosticManager &diagnostic_manager) { lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; @@ -581,7 +585,7 @@ } else { - error_stream.Printf("Need object pointer but don't know the language\n"); + diagnostic_manager.PutCString("Need object pointer but don't know the language"); return false; } @@ -591,7 +595,7 @@ if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + diagnostic_manager.Printf("warning: couldn't get required object pointer (substituting NULL): %s", object_ptr_error.AsCString()); object_ptr = 0; } @@ -603,7 +607,7 @@ 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("warning: couldn't get cmd pointer (substituting NULL): %s", object_ptr_error.AsCString()); cmd_ptr = 0; } } Index: source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -126,7 +126,7 @@ } bool - Install (Stream &error_stream, ExecutionContext &exe_ctx) override; + Install (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override; private: ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. Index: source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -55,8 +55,8 @@ //------------------------------------------------------------------ /// Install the utility function into a process /// -/// @param[in] error_stream -/// A stream to print parse errors and warnings to. +/// @param[in] diagnostic_manager +/// A diagnostic manager to report errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. @@ -65,12 +65,12 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool -ClangUtilityFunction::Install (Stream &error_stream, +ClangUtilityFunction::Install (DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { - error_stream.PutCString("error: already installed\n"); + diagnostic_manager.AddDiagnostic ("error: already installed"); return false; } @@ -82,7 +82,7 @@ if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.AddDiagnostic ("error: invalid target"); return false; } @@ -90,7 +90,7 @@ if (!process) { - error_stream.PutCString ("error: invalid process\n"); + diagnostic_manager.AddDiagnostic ("error: invalid process"); return false; } @@ -104,18 +104,18 @@ if (!DeclMap()->WillParse(exe_ctx, NULL)) { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + diagnostic_manager.AddDiagnostic ("error: current process state is unsuitable for expression parsing"); return false; } const bool generate_debug_info = true; ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); - unsigned num_errors = parser.Parse (error_stream); + unsigned num_errors = parser.Parse (diagnostic_manager); if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + diagnostic_manager.Printf ("error: %d errors parsing expression", num_errors); ResetDeclMap(); @@ -175,9 +175,13 @@ { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); + { + diagnostic_manager.Printf("error: %s", error_cstr); + } else - error_stream.Printf ("error: expression can't be interpreted or run\n"); + { + diagnostic_manager.PutCString("error: expression can't be interpreted or run"); + } return false; } } Index: source/Plugins/ExpressionParser/Go/GoUserExpression.h =================================================================== --- source/Plugins/ExpressionParser/Go/GoUserExpression.h +++ source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -66,11 +66,11 @@ lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); bool - Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) override; lldb::ExpressionResults - Execute(Stream &error_stream, ExecutionContext &exe_ctx, + Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) override; @@ -81,7 +81,7 @@ return true; } bool - FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, + FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override { Index: source/Plugins/ExpressionParser/Go/GoUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Go/GoUserExpression.cpp +++ source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -37,6 +37,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/GoASTContext.h" @@ -247,7 +248,7 @@ } bool -GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, +GoUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) { InstallContext(exe_ctx); @@ -256,14 +257,14 @@ return true; const char *error_cstr = m_interpreter->error().AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.Printf("error: %s", error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf("error: expression can't be interpreted or run"); return false; } lldb::ExpressionResults -GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, +GoUserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -281,7 +282,7 @@ if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant =="); - error_stream.Printf("expression needed to run but couldn't"); + diagnostic_manager.Printf("expression needed to run but couldn't"); return execution_results; } @@ -296,9 +297,9 @@ { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.Printf("error: %s", error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf("error: expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" @@ -154,7 +155,7 @@ // Now we're ready to call the function: - StreamString error_stream; + DiagnosticManager diagnostics; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; if (!m_print_object_caller_up) @@ -172,14 +173,14 @@ strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString()); return false; } - m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); + m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics); } else { m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, - error_stream); + diagnostics); } @@ -194,7 +195,7 @@ ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, &wrapper_struct_addr, options, - error_stream, + diagnostics, ret); if (results != eExpressionCompleted) { Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -36,6 +36,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/StringConvert.h" @@ -1242,7 +1243,7 @@ Address function_address; - StreamString errors; + DiagnosticManager diagnostics; const uint32_t addr_size = process->GetAddressByteSize(); @@ -1279,12 +1280,15 @@ } else { - errors.Clear(); + diagnostics.Clear(); - if (!m_get_class_info_code->Install(errors, exe_ctx)) + if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf ("Failed to install implementation lookup"); + diagnostics.Dump(log); + } m_get_class_info_code.reset(); } } @@ -1319,13 +1323,17 @@ if (!get_class_info_function) { if (log) - log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData()); + { + log->Printf ("Failed to get implementation lookup function caller."); + diagnostics.Dump(log); + } + return false; } arguments = get_class_info_function->GetArgumentValues(); } - errors.Clear(); + diagnostics.Clear(); const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; @@ -1345,13 +1353,13 @@ bool success = false; - errors.Clear(); + diagnostics.Clear(); // Write our function arguments into the process so we can run our function if (get_class_info_function->WriteFunctionArguments (exe_ctx, m_get_class_info_args, arguments, - errors)) + diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1366,13 +1374,13 @@ return_value.SetCompilerType (clang_uint32_t_type); return_value.GetScalar() = 0; - errors.Clear(); + diagnostics.Clear(); // Run the function ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx, &m_get_class_info_args, options, - errors, + diagnostics, return_value); if (results == eExpressionCompleted) @@ -1399,13 +1407,19 @@ else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing function arguments."); + diagnostics.Dump(log); + } } // Deallocate the memory we allocated for the ClassInfo array @@ -1486,7 +1500,7 @@ Address function_address; - StreamString errors; + DiagnosticManager diagnostics; const uint32_t addr_size = process->GetAddressByteSize(); @@ -1528,12 +1542,15 @@ } else { - errors.Clear(); + diagnostics.Clear(); - if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf ("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_get_shared_cache_class_info_code.reset(); } } @@ -1570,7 +1587,7 @@ arguments = get_shared_cache_class_info_function->GetArgumentValues(); } - errors.Clear(); + diagnostics.Clear(); const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; @@ -1591,13 +1608,13 @@ bool success = false; bool any_found = false; - errors.Clear(); + diagnostics.Clear(); // Write our function arguments into the process so we can run our function if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, m_get_shared_cache_class_info_args, arguments, - errors)) + diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1612,13 +1629,13 @@ return_value.SetCompilerType (clang_uint32_t_type); return_value.GetScalar() = 0; - errors.Clear(); + diagnostics.Clear(); // Run the function ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx, &m_get_shared_cache_class_info_args, options, - errors, + diagnostics, return_value); if (results == eExpressionCompleted) @@ -1666,13 +1683,19 @@ else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing function arguments."); + diagnostics.Dump(log); + } } // Deallocate the memory we allocated for the ClassInfo array Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -22,8 +22,9 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangASTContext.h" @@ -741,7 +742,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values) { ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; + DiagnosticManager diagnostics; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *impl_function_caller = nullptr; @@ -769,10 +770,13 @@ return args_addr; } - if (!m_impl_code->Install(errors, exe_ctx)) + if (!m_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf ("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_impl_code.reset(); return args_addr; } @@ -781,7 +785,6 @@ { if (log) log->Printf("No method lookup implementation code."); - errors.Printf ("No method lookup implementation code found."); return LLDB_INVALID_ADDRESS; } @@ -807,16 +810,19 @@ } } - errors.Clear(); + diagnostics.Clear(); // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors)) + if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing function arguments."); + diagnostics.Dump(log); + } return args_addr; } Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -15,6 +15,7 @@ #include "AppleObjCTrampolineHandler.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" @@ -75,7 +76,7 @@ { if (!m_func_sp) { - StreamString errors; + DiagnosticManager diagnostics; m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values); if (m_args_addr == LLDB_INVALID_ADDRESS) @@ -92,7 +93,7 @@ m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx, m_args_addr, options, - errors); + diagnostics); m_func_sp->SetOkayToDiscard(true); m_thread.QueueThreadPlan (m_func_sp, false); } Index: source/Plugins/Process/Utility/InferiorCallPOSIX.cpp =================================================================== --- source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ExecutionContext.h" @@ -103,7 +104,7 @@ options)); if (call_plan_sp) { - StreamFile error_strm; + DiagnosticManager diagnostics; StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) @@ -113,7 +114,7 @@ ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, - error_strm); + diagnostics); if (result == eExpressionCompleted) { @@ -186,7 +187,7 @@ options)); if (call_plan_sp) { - StreamFile error_strm; + DiagnosticManager diagnostics; StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) @@ -196,7 +197,7 @@ ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, - error_strm); + diagnostics); if (result == eExpressionCompleted) { return true; @@ -241,7 +242,7 @@ options)); if (call_plan_sp) { - StreamString error_strm; + DiagnosticManager diagnostics; StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) @@ -251,7 +252,7 @@ ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, - error_strm); + diagnostics); if (result == eExpressionCompleted) { returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); Index: source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -135,7 +136,7 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist) { ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; + DiagnosticManager diagnostics; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_item_info_caller = nullptr; @@ -162,10 +163,13 @@ return args_addr; } - if (!m_get_item_info_impl_code->Install(errors, exe_ctx)) + if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-item-info introspection: %s.", errors.GetData()); + { + log->Printf ("Failed to install get-item-info introspection."); + diagnostics.Dump(log); + } m_get_item_info_impl_code.reset(); return args_addr; } @@ -174,7 +178,6 @@ { if (log) log->Printf("No get-item-info introspection code found."); - errors.Printf ("No get-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } @@ -208,16 +211,20 @@ } } - errors.Clear(); + diagnostics.Clear(); // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, errors)) + if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing get-item-info function arguments."); + diagnostics.Dump(log); + } + return args_addr; } @@ -324,7 +331,7 @@ addr_t args_addr = SetupGetItemInfoFunction (thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; options.SetUnwindOnError (true); @@ -352,7 +359,7 @@ return return_value; } - func_call_ret = func_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = func_caller->ExecuteFunction (exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -139,7 +140,7 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, ValueList &get_pending_items_arglist) { ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; + DiagnosticManager diagnostics; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_pending_items_caller = nullptr; @@ -166,10 +167,13 @@ return args_addr; } - if (!m_get_pending_items_impl_code->Install(errors, exe_ctx)) + if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install pending-items introspection: %s.", errors.GetData()); + { + log->Printf ("Failed to install pending-items introspection."); + diagnostics.Dump(log); + } m_get_pending_items_impl_code.reset(); return args_addr; } @@ -199,7 +203,7 @@ } - errors.Clear(); + diagnostics.Clear(); if (get_pending_items_caller == nullptr) { @@ -212,13 +216,17 @@ // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, errors)) + if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { if (log) - log->Printf ("Error writing pending-items function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing pending-items function arguments."); + diagnostics.Dump(log); + } + return args_addr; } - + return args_addr; } @@ -324,7 +332,7 @@ addr_t args_addr = SetupGetPendingItemsFunction (thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; FunctionCaller *get_pending_items_caller = m_get_pending_items_impl_code->GetFunctionCaller(); @@ -345,7 +353,7 @@ ExpressionResults func_call_ret; Value results; - func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -148,7 +149,7 @@ { ExecutionContext exe_ctx (thread.shared_from_this()); Address impl_code_address; - StreamString errors; + DiagnosticManager diagnostics; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; @@ -176,10 +177,13 @@ return args_addr; } - if (!m_get_queues_impl_code_up->Install(errors, exe_ctx)) + if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install queues introspection: %s.", errors.GetData()); + { + log->Printf ("Failed to install queues introspection"); + diagnostics.Dump(log); + } m_get_queues_impl_code_up.reset(); return args_addr; } @@ -187,8 +191,10 @@ else { if (log) - log->Printf("No queues introspection code found."); - errors.Printf ("No queues introspection code found."); + { + log->Printf ("No queues introspection code found."); + diagnostics.Dump(log); + } return LLDB_INVALID_ADDRESS; } } @@ -208,16 +214,19 @@ } } - errors.Clear(); + diagnostics.Clear(); // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, errors)) + if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-queues function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing get-queues function arguments."); + diagnostics.Dump(log); + } return args_addr; } @@ -332,7 +341,7 @@ return return_value; } - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; options.SetUnwindOnError (true); @@ -344,7 +353,7 @@ ExpressionResults func_call_ret; Value results; - func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/Expression.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" @@ -143,7 +144,7 @@ { ExecutionContext exe_ctx (thread.shared_from_this()); Address impl_code_address; - StreamString errors; + DiagnosticManager diagnostics; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_thread_item_info_caller = nullptr; @@ -172,10 +173,14 @@ return args_addr; } - if (!m_get_thread_item_info_impl_code->Install(errors, exe_ctx)) + if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-thread-item-info introspection: %s.", errors.GetData()); + { + log->Printf ("Failed to install get-thread-item-info introspection."); + diagnostics.Dump(log); + } + m_get_thread_item_info_impl_code.reset(); return args_addr; } @@ -184,7 +189,6 @@ { if (log) log->Printf("No get-thread-item-info introspection code found."); - errors.Printf ("No get-thread-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } @@ -211,16 +215,19 @@ } } - errors.Clear(); + diagnostics.Clear(); // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, errors)) + if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-thread-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf ("Error writing get-thread-item-info function arguments"); + diagnostics.Dump(log); + } return args_addr; } @@ -326,7 +333,7 @@ addr_t args_addr = SetupGetThreadItemInfoFunction (thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; FunctionCaller *get_thread_item_info_caller = nullptr; @@ -354,7 +361,7 @@ ExpressionResults func_call_ret; Value results; - func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -686,7 +686,7 @@ m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); } - void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const Diagnostic &info) + void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { if (m_log) { Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -25,6 +25,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/ConnectionFileDescriptor.h" @@ -5197,32 +5198,32 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, const EvaluateExpressionOptions &options, - Stream &errors) + DiagnosticManager &diagnostic_manager) { ExpressionResults return_value = eExpressionSetupError; if (!thread_plan_sp) { - errors.Printf("RunThreadPlan called with empty thread plan."); + diagnostic_manager.PutCString("RunThreadPlan called with empty thread plan."); return eExpressionSetupError; } if (!thread_plan_sp->ValidatePlan(nullptr)) { - errors.Printf ("RunThreadPlan called with an invalid thread plan."); + diagnostic_manager.PutCString("RunThreadPlan called with an invalid thread plan."); return eExpressionSetupError; } if (exe_ctx.GetProcessPtr() != this) { - errors.Printf("RunThreadPlan called on wrong process."); + diagnostic_manager.PutCString("RunThreadPlan called on wrong process."); return eExpressionSetupError; } Thread *thread = exe_ctx.GetThreadPtr(); if (thread == nullptr) { - errors.Printf("RunThreadPlan called with invalid thread."); + diagnostic_manager.PutCString("RunThreadPlan called with invalid thread."); return eExpressionSetupError; } @@ -5245,7 +5246,7 @@ if (m_private_state.GetValue() != eStateStopped) { - errors.Printf ("RunThreadPlan called while the private state was not stopped."); + diagnostic_manager.PutCString("RunThreadPlan called while the private state was not stopped."); return eExpressionSetupError; } @@ -5258,7 +5259,7 @@ selected_frame_sp = thread->GetSelectedFrame(); if (!selected_frame_sp) { - errors.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id); + diagnostic_manager.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id); return eExpressionSetupError; } } @@ -5400,7 +5401,7 @@ { if (timeout_usec < option_one_thread_timeout) { - errors.Printf("RunThreadPlan called without one thread timeout greater than total timeout"); + diagnostic_manager.PutCString("RunThreadPlan called without one thread timeout greater than total timeout"); return eExpressionSetupError; } computed_one_thread_timeout = option_one_thread_timeout; @@ -5431,7 +5432,7 @@ Event *other_events = listener_sp->PeekAtNextEvent(); if (other_events != nullptr) { - errors.Printf("Calling RunThreadPlan with pending events on the queue."); + diagnostic_manager.PutCString("Calling RunThreadPlan with pending events on the queue."); return eExpressionSetupError; } @@ -5476,9 +5477,9 @@ Error resume_error = PrivateResume (); if (!resume_error.Success()) { - errors.Printf("Error resuming inferior the %d time: \"%s\".\n", - num_resumes, - resume_error.AsCString()); + diagnostic_manager.Printf("Error resuming inferior the %d time: \"%s\".", + num_resumes, + resume_error.AsCString()); return_value = eExpressionSetupError; break; } @@ -5494,7 +5495,7 @@ log->Printf ("Process::RunThreadPlan(): didn't get any event after resume %d, exiting.", num_resumes); - errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes); + diagnostic_manager.Printf("Didn't get any event after resume %d, exiting.", num_resumes); return_value = eExpressionSetupError; break; } @@ -5527,8 +5528,8 @@ Halt(clear_thread_plans, use_run_lock); } - errors.Printf("Didn't get running event after initial resume, got %s instead.", - StateAsCString(stop_state)); + diagnostic_manager.Printf("Didn't get running event after initial resume, got %s instead.", + StateAsCString(stop_state)); return_value = eExpressionSetupError; break; } @@ -5622,7 +5623,7 @@ const bool use_run_lock = false; Halt(clear_thread_plans, use_run_lock); return_value = eExpressionInterrupted; - errors.Printf ("Execution halted by user interrupt."); + diagnostic_manager.PutCString ("Execution halted by user interrupt."); if (log) log->Printf ("Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting."); break; @@ -5727,7 +5728,7 @@ if (stop_state == eStateExited) event_to_broadcast_sp = event_sp; - errors.Printf ("Execution stopped with unexpected state.\n"); + diagnostic_manager.PutCString ("Execution stopped with unexpected state."); return_value = eExpressionInterrupted; break; } Index: source/Target/ThreadPlanCallUserExpression.cpp =================================================================== --- source/Target/ThreadPlanCallUserExpression.cpp +++ source/Target/ThreadPlanCallUserExpression.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/HostInfo.h" @@ -91,11 +92,11 @@ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); function_stack_top = function_stack_pointer; - StreamString error_stream; + DiagnosticManager diagnostics; ExecutionContext exe_ctx(GetThread()); - m_user_expression_sp->FinalizeJITExecution(error_stream, exe_ctx, m_result_var_sp, function_stack_bottom, function_stack_top); + m_user_expression_sp->FinalizeJITExecution(diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom, function_stack_top); } ThreadPlan::MischiefManaged ();