diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 4902fc3d376f7..be72df2c68fae 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -256,17 +256,17 @@ class Debugger : public std::enable_shared_from_this, bool GetAutoConfirm() const; - const FormatEntity::Entry *GetDisassemblyFormat() const; + FormatEntity::Entry GetDisassemblyFormat() const; - const FormatEntity::Entry *GetFrameFormat() const; + FormatEntity::Entry GetFrameFormat() const; - const FormatEntity::Entry *GetFrameFormatUnique() const; + FormatEntity::Entry GetFrameFormatUnique() const; uint64_t GetStopDisassemblyMaxSize() const; - const FormatEntity::Entry *GetThreadFormat() const; + FormatEntity::Entry GetThreadFormat() const; - const FormatEntity::Entry *GetThreadStopFormat() const; + FormatEntity::Entry GetThreadStopFormat() const; lldb::ScriptLanguage GetScriptLanguage() const; @@ -310,7 +310,8 @@ class Debugger : public std::enable_shared_from_this, bool GetShowStatusline() const; - const FormatEntity::Entry *GetStatuslineFormat() const; + FormatEntity::Entry GetStatuslineFormat() const; + bool SetStatuslineFormat(const FormatEntity::Entry &format); llvm::StringRef GetSeparator() const; bool SetSeparator(llvm::StringRef s); diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h index 1aed3c6ff9e9d..18257161eec7b 100644 --- a/lldb/include/lldb/Core/FormatEntity.h +++ b/lldb/include/lldb/Core/FormatEntity.h @@ -205,6 +205,8 @@ struct Entry { return true; } + operator bool() const { return type != Type::Invalid; } + std::vector &GetChildren(); std::string string; @@ -217,7 +219,7 @@ struct Entry { size_t level = 0; /// @} - Type type; + Type type = Type::Invalid; lldb::Format fmt = lldb::eFormatDefault; lldb::addr_t number = 0; bool deref = false; diff --git a/lldb/include/lldb/Interpreter/OptionValue.h b/lldb/include/lldb/Interpreter/OptionValue.h index d19c8b8fab622..b8a92db30b252 100644 --- a/lldb/include/lldb/Interpreter/OptionValue.h +++ b/lldb/include/lldb/Interpreter/OptionValue.h @@ -72,7 +72,7 @@ class OptionValue { virtual ~OptionValue() = default; OptionValue(const OptionValue &other); - + OptionValue& operator=(const OptionValue &other); // Subclasses should override these functions @@ -292,6 +292,8 @@ class OptionValue { return GetStringValue(); if constexpr (std::is_same_v) return GetArchSpecValue(); + if constexpr (std::is_same_v) + return GetFormatEntityValue(); if constexpr (std::is_enum_v) if (std::optional value = GetEnumerationValue()) return static_cast(*value); @@ -303,11 +305,9 @@ class OptionValue { typename std::remove_pointer::type>::type, std::enable_if_t, bool> = true> T GetValueAs() const { - if constexpr (std::is_same_v) - return GetFormatEntity(); - if constexpr (std::is_same_v) - return GetRegexValue(); - return {}; + static_assert(std::is_same_v, + "only for RegularExpression"); + return GetRegexValue(); } bool SetValueAs(bool v) { return SetBooleanValue(v); } @@ -330,6 +330,10 @@ class OptionValue { bool SetValueAs(ArchSpec v) { return SetArchSpecValue(v); } + bool SetValueAs(const FormatEntity::Entry &v) { + return SetFormatEntityValue(v); + } + template , bool> = true> bool SetValueAs(T t) { return SetEnumerationValue(t); @@ -386,9 +390,11 @@ class OptionValue { std::optional GetUUIDValue() const; bool SetUUIDValue(const UUID &uuid); - const FormatEntity::Entry *GetFormatEntity() const; + FormatEntity::Entry GetFormatEntityValue() const; + bool SetFormatEntityValue(const FormatEntity::Entry &entry); + const RegularExpression *GetRegexValue() const; - + mutable std::mutex m_mutex; }; diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index 9533f9c99b0ea..1c49989c14d5c 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -399,9 +399,7 @@ class Language : public PluginInterface { /// Python uses \b except. Defaults to \b catch. virtual llvm::StringRef GetCatchKeyword() const { return "catch"; } - virtual const FormatEntity::Entry *GetFunctionNameFormat() const { - return nullptr; - } + virtual FormatEntity::Entry GetFunctionNameFormat() const { return {}; } protected: // Classes that inherit from Language can see and modify these diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 2600777c49b8c..8c37b1c8d80ec 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -290,19 +290,19 @@ bool Debugger::GetAutoConfirm() const { idx, g_debugger_properties[idx].default_uint_value != 0); } -const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { +FormatEntity::Entry Debugger::GetDisassemblyFormat() const { constexpr uint32_t idx = ePropertyDisassemblyFormat; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } -const FormatEntity::Entry *Debugger::GetFrameFormat() const { +FormatEntity::Entry Debugger::GetFrameFormat() const { constexpr uint32_t idx = ePropertyFrameFormat; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } -const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { +FormatEntity::Entry Debugger::GetFrameFormatUnique() const { constexpr uint32_t idx = ePropertyFrameFormatUnique; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } uint64_t Debugger::GetStopDisassemblyMaxSize() const { @@ -346,14 +346,14 @@ void Debugger::SetPrompt(llvm::StringRef p) { GetCommandInterpreter().UpdatePrompt(new_prompt); } -const FormatEntity::Entry *Debugger::GetThreadFormat() const { +FormatEntity::Entry Debugger::GetThreadFormat() const { constexpr uint32_t idx = ePropertyThreadFormat; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } -const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { +FormatEntity::Entry Debugger::GetThreadStopFormat() const { constexpr uint32_t idx = ePropertyThreadStopFormat; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } lldb::ScriptLanguage Debugger::GetScriptLanguage() const { @@ -480,9 +480,9 @@ bool Debugger::GetShowStatusline() const { idx, g_debugger_properties[idx].default_uint_value != 0); } -const FormatEntity::Entry *Debugger::GetStatuslineFormat() const { +FormatEntity::Entry Debugger::GetStatuslineFormat() const { constexpr uint32_t idx = ePropertyStatuslineFormat; - return GetPropertyAtIndexAs(idx); + return GetPropertyAtIndexAs(idx, {}); } llvm::StringRef Debugger::GetSeparator() const { @@ -498,6 +498,13 @@ bool Debugger::SetSeparator(llvm::StringRef s) { return ret; } +bool Debugger::SetStatuslineFormat(const FormatEntity::Entry &format) { + constexpr uint32_t idx = ePropertyStatuslineFormat; + bool ret = SetPropertyAtIndex(idx, format); + RedrawStatusline(); + return ret; +} + bool Debugger::GetUseAutosuggestion() const { const uint32_t idx = ePropertyShowAutosuggestion; return GetPropertyAtIndexAs( @@ -1532,8 +1539,11 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, FormatEntity::Entry format_entry; if (format == nullptr) { - if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) - format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) { + format_entry = + exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + format = &format_entry; + } if (format == nullptr) { FormatEntity::Parse("${addr}: ", format_entry); format = &format_entry; diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 07e41466b4bc9..501ee2f459d78 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -309,8 +309,8 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, const FormatEntity::Entry *disassembly_format = nullptr; FormatEntity::Entry format; if (exe_ctx.HasTargetScope()) { - disassembly_format = - exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); + format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); + disassembly_format = &format; } else { FormatEntity::Parse("${addr}: ", format); disassembly_format = &format; @@ -1013,8 +1013,8 @@ void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, const FormatEntity::Entry *disassembly_format = nullptr; FormatEntity::Entry format; if (exe_ctx && exe_ctx->HasTargetScope()) { - disassembly_format = - exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + disassembly_format = &format; } else { FormatEntity::Parse("${addr}: ", format); disassembly_format = &format; diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index 4db5fd37a0285..6261856f7c3da 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -1279,13 +1279,13 @@ static bool FormatFunctionNameForLanguage(Stream &s, if (!language_plugin) return false; - const auto *format = language_plugin->GetFunctionNameFormat(); + FormatEntity::Entry format = language_plugin->GetFunctionNameFormat(); if (!format) return false; StreamString name_stream; const bool success = - FormatEntity::Format(*format, name_stream, sc, exe_ctx, /*addr=*/nullptr, + FormatEntity::Format(format, name_stream, sc, exe_ctx, /*addr=*/nullptr, /*valobj=*/nullptr, /*function_changed=*/false, /*initial_function=*/false); if (success) diff --git a/lldb/source/Core/Statusline.cpp b/lldb/source/Core/Statusline.cpp index e14691e2538a2..dcfa84815dc03 100644 --- a/lldb/source/Core/Statusline.cpp +++ b/lldb/source/Core/Statusline.cpp @@ -146,9 +146,9 @@ void Statusline::Redraw(bool update) { } StreamString stream; - if (auto *format = m_debugger.GetStatuslineFormat()) - FormatEntity::Format(*format, stream, &symbol_ctx, &exe_ctx, nullptr, - nullptr, false, false); + FormatEntity::Entry format = m_debugger.GetStatuslineFormat(); + FormatEntity::Format(format, stream, &symbol_ctx, &exe_ctx, nullptr, nullptr, + false, false); - Draw(std::string(stream.GetString())); + Draw(stream.GetString().str()); } diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp index b95f4fec33949..aa118107f27c5 100644 --- a/lldb/source/Interpreter/OptionValue.cpp +++ b/lldb/source/Interpreter/OptionValue.cpp @@ -380,11 +380,11 @@ bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { return false; } -const FormatEntity::Entry *OptionValue::GetFormatEntity() const { +FormatEntity::Entry OptionValue::GetFormatEntityValue() const { std::lock_guard lock(m_mutex); if (const OptionValueFormatEntity *option_value = GetAsFormatEntity()) - return &option_value->GetCurrentValue(); - return nullptr; + return option_value->GetCurrentValue(); + return {}; } const RegularExpression *OptionValue::GetRegexValue() const { @@ -474,6 +474,15 @@ bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) { return false; } +bool OptionValue::SetFormatEntityValue(const FormatEntity::Entry &entry) { + std::lock_guard lock(m_mutex); + if (OptionValueFormatEntity *option_value = GetAsFormatEntity()) { + option_value->SetCurrentValue(entry); + return true; + } + return false; +} + const char *OptionValue::GetBuiltinTypeAsCString(Type t) { switch (t) { case eTypeInvalid: diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp index 2a630b8758224..7ec651ea61560 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp @@ -303,7 +303,16 @@ Status SwiftREPL::DoInitialization() { std::static_pointer_cast( *type_system_or_err) ->SetCompilerOptions(m_compiler_options.c_str()); - return Status(); + + std::string format_str = "${ansi.negative}Swift " + + swift::version::getCompilerVersion() + + "{ | {${progress.count} }${progress.message}}"; + FormatEntity::Entry format_entry; + Status error = FormatEntity::Parse(format_str, format_entry); + if (error.Success()) + m_target.GetDebugger().SetStatuslineFormat(format_entry); + + return error; } llvm::StringRef SwiftREPL::GetSourceFileBasename() { diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 19eee054433b4..a37dc6baa9f23 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -2079,9 +2079,9 @@ class PluginProperties : public Properties { m_collection_sp->Initialize(g_language_cplusplus_properties); } - const FormatEntity::Entry *GetFunctionNameFormat() const { - return GetPropertyAtIndexAs( - ePropertyFunctionNameFormat); + FormatEntity::Entry GetFunctionNameFormat() const { + return GetPropertyAtIndexAs( + ePropertyFunctionNameFormat, {}); } }; } // namespace @@ -2091,7 +2091,7 @@ static PluginProperties &GetGlobalPluginProperties() { return g_settings; } -const FormatEntity::Entry *CPlusPlusLanguage::GetFunctionNameFormat() const { +FormatEntity::Entry CPlusPlusLanguage::GetFunctionNameFormat() const { return GetGlobalPluginProperties().GetFunctionNameFormat(); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index 8dd487d54cc7d..9df771c90181e 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -131,8 +131,8 @@ class CPlusPlusLanguage : public Language { static llvm::StringRef GetPluginNameStatic() { return "cplusplus"; } bool SymbolNameFitsToLanguage(Mangled mangled) const override; - - bool DemangledNameContainsPath(llvm::StringRef path, + + bool DemangledNameContainsPath(llvm::StringRef path, ConstString demangled) const override; ConstString @@ -174,7 +174,7 @@ class CPlusPlusLanguage : public Language { llvm::StringRef GetInstanceVariableName() override { return "this"; } - const FormatEntity::Entry *GetFunctionNameFormat() const override; + FormatEntity::Entry GetFunctionNameFormat() const override; // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 98be6ed4499ed..18444bb8fb94d 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1910,12 +1910,15 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, ExecutionContext exe_ctx(shared_from_this()); const FormatEntity::Entry *frame_format = nullptr; + FormatEntity::Entry format_entry; Target *target = exe_ctx.GetTargetPtr(); if (target) { if (show_unique) { - frame_format = target->GetDebugger().GetFrameFormatUnique(); + format_entry = target->GetDebugger().GetFrameFormatUnique(); + frame_format = &format_entry; } else { - frame_format = target->GetDebugger().GetFrameFormat(); + format_entry = target->GetDebugger().GetFrameFormat(); + frame_format = &format_entry; } } if (!DumpUsingFormat(*strm, frame_format, frame_marker)) { diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index a988eb24ff791..947016b13a9ad 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -1694,10 +1694,14 @@ void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, ExecutionContext exe_ctx(shared_from_this()); const FormatEntity::Entry *thread_format; - if (stop_format) - thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); - else - thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); + FormatEntity::Entry format_entry; + if (stop_format) { + format_entry = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); + thread_format = &format_entry; + } else { + format_entry = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); + thread_format = &format_entry; + } assert(thread_format); diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp index 9f661b3c59478..3b91adc8abe89 100644 --- a/lldb/source/Target/ThreadPlanTracer.cpp +++ b/lldb/source/Target/ThreadPlanTracer.cpp @@ -175,11 +175,11 @@ void ThreadPlanAssemblyTracer::Log() { const bool show_control_flow_kind = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); - const FormatEntity::Entry *disassemble_format = + FormatEntity::Entry disassemble_format = m_process.GetTarget().GetDebugger().GetDisassemblyFormat(); instruction->Dump(stream_sp.get(), max_opcode_byte_size, show_address, show_bytes, show_control_flow_kind, nullptr, nullptr, - nullptr, disassemble_format, 0); + nullptr, &disassemble_format, 0); } } } diff --git a/lldb/unittests/Core/CMakeLists.txt b/lldb/unittests/Core/CMakeLists.txt index 949963fd40346..f06fcd250cf7d 100644 --- a/lldb/unittests/Core/CMakeLists.txt +++ b/lldb/unittests/Core/CMakeLists.txt @@ -1,4 +1,5 @@ add_lldb_unittest(LLDBCoreTests + DebuggerTest.cpp CommunicationTest.cpp DiagnosticEventTest.cpp DumpDataExtractorTest.cpp diff --git a/lldb/unittests/Core/DebuggerTest.cpp b/lldb/unittests/Core/DebuggerTest.cpp new file mode 100644 index 0000000000000..4dccd912c63ae --- /dev/null +++ b/lldb/unittests/Core/DebuggerTest.cpp @@ -0,0 +1,52 @@ +//===-- DebuggerTest.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Debugger.h" +#include "Plugins/Platform/MacOSX/PlatformMacOSX.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "gtest/gtest.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { +class DebuggerTest : public ::testing::Test { +public: + void SetUp() override { + FileSystem::Initialize(); + HostInfo::Initialize(); + PlatformMacOSX::Initialize(); + std::call_once(TestUtilities::g_debugger_initialize_flag, + []() { Debugger::Initialize(nullptr); }); + ArchSpec arch("x86_64-apple-macosx-"); + Platform::SetHostPlatform( + PlatformRemoteMacOSX::CreateInstance(true, &arch)); + } + void TearDown() override { + PlatformMacOSX::Terminate(); + HostInfo::Terminate(); + FileSystem::Terminate(); + } +}; +} // namespace + +TEST_F(DebuggerTest, TestSettings) { + DebuggerSP debugger_sp = Debugger::CreateInstance(); + + EXPECT_TRUE(debugger_sp->SetUseColor(true)); + EXPECT_TRUE(debugger_sp->GetUseColor()); + + FormatEntity::Entry format("foo"); + EXPECT_TRUE(debugger_sp->SetStatuslineFormat(format)); + EXPECT_EQ(debugger_sp->GetStatuslineFormat().string, "foo"); + + Debugger::Destroy(debugger_sp); +}