tatyana-krasnukha created this revision. tatyana-krasnukha added reviewers: clayborg, JDevlieghere, labath, teemperor. tatyana-krasnukha added a project: LLDB. Herald added a subscriber: mgorny. tatyana-krasnukha requested review of this revision. Herald added a subscriber: lldb-commits.
Some implementations of the DeepCopy function called the copy constructor that copied m_parent member instead of setting a new parent. Others just lived the base class's members (m_parent, m_callback, m_was_set) empty. One more problem is that not all classes override this function, e.g. OptionValueArgs::DeepCopy produces OptionValueArray instance, and Target[Process/Thread]ValueProperty::DeepCopy produces OptionValueProperty. This makes downcasting via static_cast invalid. This patch adds a virtual Clone function, which implements well-known idiom "virtual constructor", and overrides it in every derived class. DeepCopy calls Clone to instantiate an object of a correct type. It also sets valid m_parent. Add a test that checks DeepCopy for correct copying/setting all data members of the base class. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D96817 Files: lldb/include/lldb/Interpreter/OptionValue.h lldb/include/lldb/Interpreter/OptionValueArch.h lldb/include/lldb/Interpreter/OptionValueArgs.h lldb/include/lldb/Interpreter/OptionValueArray.h lldb/include/lldb/Interpreter/OptionValueBoolean.h lldb/include/lldb/Interpreter/OptionValueChar.h lldb/include/lldb/Interpreter/OptionValueDictionary.h lldb/include/lldb/Interpreter/OptionValueEnumeration.h lldb/include/lldb/Interpreter/OptionValueFileColonLine.h lldb/include/lldb/Interpreter/OptionValueFileSpec.h lldb/include/lldb/Interpreter/OptionValueFileSpecList.h lldb/include/lldb/Interpreter/OptionValueFormat.h lldb/include/lldb/Interpreter/OptionValueFormatEntity.h lldb/include/lldb/Interpreter/OptionValueLanguage.h lldb/include/lldb/Interpreter/OptionValuePathMappings.h lldb/include/lldb/Interpreter/OptionValueProperties.h lldb/include/lldb/Interpreter/OptionValueRegex.h lldb/include/lldb/Interpreter/OptionValueSInt64.h lldb/include/lldb/Interpreter/OptionValueString.h lldb/include/lldb/Interpreter/OptionValueUInt64.h lldb/include/lldb/Interpreter/OptionValueUUID.h lldb/include/lldb/Target/Target.h lldb/source/Interpreter/OptionValue.cpp lldb/source/Interpreter/OptionValueArch.cpp lldb/source/Interpreter/OptionValueArgs.cpp lldb/source/Interpreter/OptionValueArray.cpp lldb/source/Interpreter/OptionValueBoolean.cpp lldb/source/Interpreter/OptionValueChar.cpp lldb/source/Interpreter/OptionValueDictionary.cpp lldb/source/Interpreter/OptionValueEnumeration.cpp lldb/source/Interpreter/OptionValueFileColonLine.cpp lldb/source/Interpreter/OptionValueFileSpec.cpp lldb/source/Interpreter/OptionValueFileSpecList.cpp lldb/source/Interpreter/OptionValueFormat.cpp lldb/source/Interpreter/OptionValueFormatEntity.cpp lldb/source/Interpreter/OptionValueLanguage.cpp lldb/source/Interpreter/OptionValuePathMappings.cpp lldb/source/Interpreter/OptionValueProperties.cpp lldb/source/Interpreter/OptionValueRegex.cpp lldb/source/Interpreter/OptionValueSInt64.cpp lldb/source/Interpreter/OptionValueString.cpp lldb/source/Interpreter/OptionValueUInt64.cpp lldb/source/Interpreter/OptionValueUUID.cpp lldb/source/Target/Process.cpp lldb/source/Target/Target.cpp lldb/source/Target/Thread.cpp lldb/test/API/commands/settings/TestSettings.py lldb/unittests/Interpreter/CMakeLists.txt lldb/unittests/Interpreter/TestOptionValue.cpp
Index: lldb/unittests/Interpreter/TestOptionValue.cpp =================================================================== --- /dev/null +++ lldb/unittests/Interpreter/TestOptionValue.cpp @@ -0,0 +1,175 @@ +//===-- TestOptionValue.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/Interpreter/OptionValues.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +class Callback { +public: + virtual void Invoke() const {} + void operator()() const { Invoke(); } +}; + +class MockCallback : public Callback { +public: + MOCK_CONST_METHOD0(Invoke, void()); +}; + +// Test a single-value class. +TEST(OptionValueString, DeepCopy) { + OptionValueString str; + str.SetValueFromString(llvm::StringRef("ab")); + + MockCallback callback; + str.SetValueChangedCallback([&callback] { callback(); }); + EXPECT_CALL(callback, Invoke()); + + auto copy_sp = str.DeepCopy(nullptr); + + // Test that the base class data members are copied/set correctly. + ASSERT_TRUE(copy_sp); + ASSERT_EQ(copy_sp->GetParent().get(), nullptr); + ASSERT_TRUE(copy_sp->OptionWasSet()); + ASSERT_EQ(copy_sp->GetStringValue(), "ab"); + + // Trigger the callback. + copy_sp->SetValueFromString(llvm::StringRef("c"), eVarSetOperationAppend); + ASSERT_EQ(copy_sp->GetStringValue(), "abc"); +} + +// Test an aggregate class. +TEST(OptionValueArgs, DeepCopy) { + OptionValueArgs args; + args.SetValueFromString(llvm::StringRef("A B")); + + MockCallback callback; + args.SetValueChangedCallback([&callback] { callback(); }); + EXPECT_CALL(callback, Invoke()); + + auto copy_sp = args.DeepCopy(nullptr); + + // Test that the base class data members are copied/set correctly. + ASSERT_TRUE(copy_sp); + ASSERT_EQ(copy_sp->GetParent(), nullptr); + ASSERT_TRUE(copy_sp->OptionWasSet()); + + auto *args_copy_ptr = copy_sp->GetAsArgs(); + ASSERT_EQ(args_copy_ptr->GetSize(), 2U); + ASSERT_EQ((*args_copy_ptr)[0]->GetParent(), copy_sp); + ASSERT_EQ((*args_copy_ptr)[0]->GetStringValue(), "A"); + ASSERT_EQ((*args_copy_ptr)[1]->GetParent(), copy_sp); + ASSERT_EQ((*args_copy_ptr)[1]->GetStringValue(), "B"); + + // Trigger the callback. + copy_sp->SetValueFromString(llvm::StringRef("C"), eVarSetOperationAppend); + ASSERT_TRUE(args_copy_ptr); + ASSERT_EQ(args_copy_ptr->GetSize(), 3U); + ASSERT_EQ((*args_copy_ptr)[2]->GetStringValue(), "C"); +} + +class TestProperties : public OptionValueProperties { +public: + static std::shared_ptr<TestProperties> CreateGlobal() { + auto props_sp = std::make_shared<TestProperties>(); + const bool is_global = false; + + auto dict_sp = std::make_shared<OptionValueDictionary>(1 << eTypeUInt64); + props_sp->AppendProperty(ConstString("dict"), ConstString(), is_global, + dict_sp); + + auto file_list_sp = std::make_shared<OptionValueFileSpecList>(); + props_sp->AppendProperty(ConstString("file-list"), ConstString(), is_global, + file_list_sp); + return props_sp; + } + + void SetDictionaryChangedCallback(const MockCallback &callback) { + SetValueChangedCallback(m_dict_index, [&callback] { callback(); }); + } + + void SetFileListChangedCallback(const MockCallback &callback) { + SetValueChangedCallback(m_file_list_index, [&callback] { callback(); }); + } + + OptionValueDictionary *GetDictionary() { + return GetPropertyAtIndexAsOptionValueDictionary(nullptr, m_dict_index); + } + + OptionValueFileSpecList *GetFileList() { + return GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, + m_file_list_index); + } + +private: + lldb::OptionValueSP Clone() const { + return std::make_shared<TestProperties>(*this); + } + + uint32_t m_dict_index = 0; + uint32_t m_file_list_index = 1; +}; + +// Test a user-defined propery class. +TEST(TestProperties, DeepCopy) { + auto props_sp = TestProperties::CreateGlobal(); + props_sp->GetDictionary()->SetValueFromString(llvm::StringRef({"A=1 B=2"})); + props_sp->GetFileList()->SetValueFromString(llvm::StringRef("path/to/file")); + + MockCallback callback; + props_sp->SetDictionaryChangedCallback(callback); + props_sp->SetFileListChangedCallback(callback); + EXPECT_CALL(callback, Invoke()).Times(2); + + auto copy_sp = props_sp->DeepCopy(nullptr); + + // Test that the base class data members are copied/set correctly. + ASSERT_TRUE(copy_sp); + ASSERT_EQ(copy_sp->GetParent(), nullptr); + + // This cast is safe only if the class overrides Clone(). + auto *props_copy_ptr = static_cast<TestProperties *>(copy_sp.get()); + ASSERT_TRUE(props_copy_ptr); + + // Test the first child. + auto dict_copy_ptr = props_copy_ptr->GetDictionary(); + ASSERT_TRUE(dict_copy_ptr); + ASSERT_EQ(dict_copy_ptr->GetParent(), copy_sp); + ASSERT_TRUE(dict_copy_ptr->OptionWasSet()); + ASSERT_EQ(dict_copy_ptr->GetNumValues(), 2U); + + auto value_ptr = dict_copy_ptr->GetValueForKey(ConstString("A")); + ASSERT_TRUE(value_ptr); + ASSERT_EQ(value_ptr->GetParent().get(), dict_copy_ptr); + ASSERT_EQ(value_ptr->GetUInt64Value(), 1); + + value_ptr = dict_copy_ptr->GetValueForKey(ConstString("B")); + ASSERT_TRUE(value_ptr); + ASSERT_EQ(value_ptr->GetParent().get(), dict_copy_ptr); + ASSERT_EQ(value_ptr->GetUInt64Value(), 2); + + // Test the second child. + auto file_list_copy_ptr = props_copy_ptr->GetFileList(); + ASSERT_TRUE(file_list_copy_ptr); + ASSERT_EQ(file_list_copy_ptr->GetParent(), copy_sp); + ASSERT_TRUE(file_list_copy_ptr->OptionWasSet()); + + auto file_list_copy = file_list_copy_ptr->GetCurrentValue(); + ASSERT_EQ(file_list_copy.GetSize(), 1U); + ASSERT_EQ(file_list_copy.GetFileSpecAtIndex(0), FileSpec("path/to/file")); + + // Trigger the callback first time. + dict_copy_ptr->SetValueFromString(llvm::StringRef("C=3"), + eVarSetOperationAppend); + + // Trigger the callback second time. + file_list_copy_ptr->SetValueFromString(llvm::StringRef("0 another/path"), + eVarSetOperationReplace); +} Index: lldb/unittests/Interpreter/CMakeLists.txt =================================================================== --- lldb/unittests/Interpreter/CMakeLists.txt +++ lldb/unittests/Interpreter/CMakeLists.txt @@ -1,6 +1,7 @@ add_lldb_unittest(InterpreterTests TestCompletion.cpp TestOptionArgParser.cpp + TestOptionValue.cpp TestOptionValueFileColonLine.cpp LINK_LIBS Index: lldb/test/API/commands/settings/TestSettings.py =================================================================== --- lldb/test/API/commands/settings/TestSettings.py +++ lldb/test/API/commands/settings/TestSettings.py @@ -238,6 +238,11 @@ self.assertTrue(found_env_var, "MY_ENV_VAR was not set in LunchInfo object") + self.assertEqual(launch_info.GetNumArguments(), 3) + self.assertEqual(launch_info.GetArgumentAtIndex(0), "A") + self.assertEqual(launch_info.GetArgumentAtIndex(1), "B") + self.assertEqual(launch_info.GetArgumentAtIndex(2), "C") + self.expect( 'target show-launch-environment', substrs=["MY_ENV_VAR=YES"]) Index: lldb/source/Target/Thread.cpp =================================================================== --- lldb/source/Target/Thread.cpp +++ lldb/source/Target/Thread.cpp @@ -76,12 +76,6 @@ ThreadOptionValueProperties(ConstString name) : OptionValueProperties(name) {} - // This constructor is used when creating ThreadOptionValueProperties when it - // is part of a new lldb_private::Thread instance. It will copy all current - // global property values as needed - ThreadOptionValueProperties(ThreadProperties *global_properties) - : OptionValueProperties(*global_properties->GetValueProperties()) {} - const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override { @@ -100,6 +94,11 @@ } return ProtectedGetPropertyAtIndex(idx); } + +private: + lldb::OptionValueSP Clone() const override { + return std::make_shared<ThreadOptionValueProperties>(*this); + } }; ThreadProperties::ThreadProperties(bool is_global) : Properties() { @@ -108,8 +107,8 @@ std::make_shared<ThreadOptionValueProperties>(ConstString("thread")); m_collection_sp->Initialize(g_thread_properties); } else - m_collection_sp = std::make_shared<ThreadOptionValueProperties>( - Thread::GetGlobalProperties().get()); + m_collection_sp = + OptionValueProperties::CreateLocalCopy(*Thread::GetGlobalProperties()); } ThreadProperties::~ThreadProperties() = default; Index: lldb/source/Target/Target.cpp =================================================================== --- lldb/source/Target/Target.cpp +++ lldb/source/Target/Target.cpp @@ -3619,12 +3619,6 @@ public: TargetOptionValueProperties(ConstString name) : OptionValueProperties(name) {} - // This constructor is used when creating TargetOptionValueProperties when it - // is part of a new lldb_private::Target instance. It will copy all current - // global property values as needed - TargetOptionValueProperties(const TargetPropertiesSP &target_properties_sp) - : OptionValueProperties(*target_properties_sp->GetValueProperties()) {} - const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override { @@ -3643,6 +3637,11 @@ } return ProtectedGetPropertyAtIndex(idx); } + +private: + lldb::OptionValueSP Clone() const override { + return std::make_shared<TargetOptionValueProperties>(*this); + } }; // TargetProperties @@ -3659,6 +3658,11 @@ TargetExperimentalOptionValueProperties() : OptionValueProperties( ConstString(Properties::GetExperimentalSettingsName())) {} + +private: + lldb::OptionValueSP Clone() const override { + return std::make_shared<TargetExperimentalOptionValueProperties>(*this); + } }; TargetExperimentalProperties::TargetExperimentalProperties() @@ -3671,8 +3675,8 @@ TargetProperties::TargetProperties(Target *target) : Properties(), m_launch_info(), m_target(target) { if (target) { - m_collection_sp = std::make_shared<TargetOptionValueProperties>( - Target::GetGlobalProperties()); + m_collection_sp = + OptionValueProperties::CreateLocalCopy(*Target::GetGlobalProperties()); // Set callbacks to update launch_info whenever "settins set" updated any // of these properties @@ -4200,8 +4204,7 @@ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); } -const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() { - m_launch_info.SetArg0(GetArg0()); // FIXME: Arg0 callback doesn't work +const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() const { return m_launch_info; } Index: lldb/source/Target/Process.cpp =================================================================== --- lldb/source/Target/Process.cpp +++ lldb/source/Target/Process.cpp @@ -88,12 +88,6 @@ ProcessOptionValueProperties(ConstString name) : OptionValueProperties(name) {} - // This constructor is used when creating ProcessOptionValueProperties when - // it is part of a new lldb_private::Process instance. It will copy all - // current global property values as needed - ProcessOptionValueProperties(ProcessProperties *global_properties) - : OptionValueProperties(*global_properties->GetValueProperties()) {} - const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override { @@ -112,6 +106,11 @@ } return ProtectedGetPropertyAtIndex(idx); } + +private: + lldb::OptionValueSP Clone() const override { + return std::make_shared<ProcessOptionValueProperties>(*this); + } }; #define LLDB_PROPERTIES_process @@ -157,8 +156,8 @@ ConstString("thread"), ConstString("Settings specific to threads."), true, Thread::GetGlobalProperties()->GetValueProperties()); } else { - m_collection_sp = std::make_shared<ProcessOptionValueProperties>( - Process::GetGlobalProperties().get()); + m_collection_sp = + OptionValueProperties::CreateLocalCopy(*Process::GetGlobalProperties()); m_collection_sp->SetValueChangedCallback( ePropertyPythonOSPluginPath, [this] { m_process->LoadOperatingSystemPlugin(true); }); Index: lldb/source/Interpreter/OptionValueUUID.cpp =================================================================== --- lldb/source/Interpreter/OptionValueUUID.cpp +++ lldb/source/Interpreter/OptionValueUUID.cpp @@ -58,8 +58,8 @@ return error; } -lldb::OptionValueSP OptionValueUUID::DeepCopy() const { - return OptionValueSP(new OptionValueUUID(*this)); +lldb::OptionValueSP OptionValueUUID::Clone() const { + return std::make_shared<OptionValueUUID>(*this); } void OptionValueUUID::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueUInt64.cpp =================================================================== --- lldb/source/Interpreter/OptionValueUInt64.cpp +++ lldb/source/Interpreter/OptionValueUInt64.cpp @@ -69,6 +69,6 @@ return error; } -lldb::OptionValueSP OptionValueUInt64::DeepCopy() const { - return OptionValueSP(new OptionValueUInt64(*this)); +lldb::OptionValueSP OptionValueUInt64::Clone() const { + return std::make_shared<OptionValueUInt64>(*this); } Index: lldb/source/Interpreter/OptionValueString.cpp =================================================================== --- lldb/source/Interpreter/OptionValueString.cpp +++ lldb/source/Interpreter/OptionValueString.cpp @@ -117,8 +117,8 @@ return error; } -lldb::OptionValueSP OptionValueString::DeepCopy() const { - return OptionValueSP(new OptionValueString(*this)); +lldb::OptionValueSP OptionValueString::Clone() const { + return std::make_shared<OptionValueString>(*this); } Status OptionValueString::SetCurrentValue(llvm::StringRef value) { Index: lldb/source/Interpreter/OptionValueSInt64.cpp =================================================================== --- lldb/source/Interpreter/OptionValueSInt64.cpp +++ lldb/source/Interpreter/OptionValueSInt64.cpp @@ -71,6 +71,6 @@ return error; } -lldb::OptionValueSP OptionValueSInt64::DeepCopy() const { - return OptionValueSP(new OptionValueSInt64(*this)); +lldb::OptionValueSP OptionValueSInt64::Clone() const { + return std::make_shared<OptionValueSInt64>(*this); } Index: lldb/source/Interpreter/OptionValueRegex.cpp =================================================================== --- lldb/source/Interpreter/OptionValueRegex.cpp +++ lldb/source/Interpreter/OptionValueRegex.cpp @@ -60,6 +60,6 @@ return error; } -lldb::OptionValueSP OptionValueRegex::DeepCopy() const { - return OptionValueSP(new OptionValueRegex(m_regex.GetText().str().c_str())); +lldb::OptionValueSP OptionValueRegex::Clone() const { + return std::make_shared<OptionValueRegex>(m_regex.GetText().str().c_str()); } Index: lldb/source/Interpreter/OptionValueProperties.cpp =================================================================== --- lldb/source/Interpreter/OptionValueProperties.cpp +++ lldb/source/Interpreter/OptionValueProperties.cpp @@ -23,27 +23,6 @@ OptionValueProperties::OptionValueProperties(ConstString name) : OptionValue(), m_name(name), m_properties(), m_name_to_index() {} -OptionValueProperties::OptionValueProperties( - const OptionValueProperties &global_properties) - : OptionValue(global_properties), - std::enable_shared_from_this<OptionValueProperties>(), - m_name(global_properties.m_name), - m_properties(global_properties.m_properties), - m_name_to_index(global_properties.m_name_to_index) { - // We now have an exact copy of "global_properties". We need to now find all - // non-global settings and copy the property values so that all non-global - // settings get new OptionValue instances created for them. - const size_t num_properties = m_properties.size(); - for (size_t i = 0; i < num_properties; ++i) { - // Duplicate any values that are not global when constructing properties - // from a global copy - if (!m_properties[i].IsGlobal()) { - lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy()); - m_properties[i].SetOptionValue(new_value_sp); - } - } -} - size_t OptionValueProperties::GetNumProperties() const { return m_properties.size(); } @@ -250,38 +229,50 @@ bool OptionValueProperties::GetPropertyAtIndexAsArgs( const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); - if (property) { - OptionValue *value = property->GetValue().get(); - if (value) { - const OptionValueArray *array = value->GetAsArray(); - if (array) - return array->GetArgs(args); - else { - const OptionValueDictionary *dict = value->GetAsDictionary(); - if (dict) - return dict->GetArgs(args); - } - } - } + if (!property) + return false; + + OptionValue *value = property->GetValue().get(); + if (!value) + return false; + + const OptionValueArgs *arguments = value->GetAsArgs(); + if (arguments) + return arguments->GetArgs(args); + + const OptionValueArray *array = value->GetAsArray(); + if (array) + return array->GetArgs(args); + + const OptionValueDictionary *dict = value->GetAsDictionary(); + if (dict) + return dict->GetArgs(args); + return false; } bool OptionValueProperties::SetPropertyAtIndexFromArgs( const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) { const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); - if (property) { - OptionValue *value = property->GetValue().get(); - if (value) { - OptionValueArray *array = value->GetAsArray(); - if (array) - return array->SetArgs(args, eVarSetOperationAssign).Success(); - else { - OptionValueDictionary *dict = value->GetAsDictionary(); - if (dict) - return dict->SetArgs(args, eVarSetOperationAssign).Success(); - } - } - } + if (!property) + return false; + + OptionValue *value = property->GetValue().get(); + if (!value) + return false; + + OptionValueArgs *arguments = value->GetAsArgs(); + if (arguments) + return arguments->SetArgs(args, eVarSetOperationAssign).Success(); + + OptionValueArray *array = value->GetAsArray(); + if (array) + return array->SetArgs(args, eVarSetOperationAssign).Success(); + + OptionValueDictionary *dict = value->GetAsDictionary(); + if (dict) + return dict->SetArgs(args, eVarSetOperationAssign).Success(); + return false; } @@ -552,8 +543,36 @@ return error; } -lldb::OptionValueSP OptionValueProperties::DeepCopy() const { - llvm_unreachable("this shouldn't happen"); +OptionValuePropertiesSP +OptionValueProperties::CreateLocalCopy(const Properties &global_properties) { + auto global_props_sp = global_properties.GetValueProperties(); + lldbassert(global_props_sp); + + auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent()); + return std::static_pointer_cast<OptionValueProperties>(copy_sp); +} + +OptionValueSP OptionValueProperties::Clone() const { + return std::make_shared<OptionValueProperties>(*this); +} + +OptionValueSP +OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const { + auto copy_sp = OptionValue::DeepCopy(new_parent); + // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived + // types that override GetType returning a different value. + auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get()); + lldbassert(props_value_ptr); + + for (auto &property : props_value_ptr->m_properties) { + // Duplicate any values that are not global when constructing properties + // from a global copy. + if (!property.IsGlobal()) { + auto value_sp = property.GetValue()->DeepCopy(copy_sp); + property.SetOptionValue(value_sp); + } + } + return copy_sp; } const Property *OptionValueProperties::GetPropertyAtPath( Index: lldb/source/Interpreter/OptionValuePathMappings.cpp =================================================================== --- lldb/source/Interpreter/OptionValuePathMappings.cpp +++ lldb/source/Interpreter/OptionValuePathMappings.cpp @@ -197,6 +197,6 @@ return error; } -lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const { - return OptionValueSP(new OptionValuePathMappings(*this)); +lldb::OptionValueSP OptionValuePathMappings::Clone() const { + return std::make_shared<OptionValuePathMappings>(*this); } Index: lldb/source/Interpreter/OptionValueLanguage.cpp =================================================================== --- lldb/source/Interpreter/OptionValueLanguage.cpp +++ lldb/source/Interpreter/OptionValueLanguage.cpp @@ -70,6 +70,6 @@ return error; } -lldb::OptionValueSP OptionValueLanguage::DeepCopy() const { - return OptionValueSP(new OptionValueLanguage(*this)); +lldb::OptionValueSP OptionValueLanguage::Clone() const { + return std::make_shared<OptionValueLanguage>(*this); } Index: lldb/source/Interpreter/OptionValueFormatEntity.cpp =================================================================== --- lldb/source/Interpreter/OptionValueFormatEntity.cpp +++ lldb/source/Interpreter/OptionValueFormatEntity.cpp @@ -111,8 +111,8 @@ return error; } -lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const { - return OptionValueSP(new OptionValueFormatEntity(*this)); +lldb::OptionValueSP OptionValueFormatEntity::Clone() const { + return std::make_shared<OptionValueFormatEntity>(*this); } void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueFormat.cpp =================================================================== --- lldb/source/Interpreter/OptionValueFormat.cpp +++ lldb/source/Interpreter/OptionValueFormat.cpp @@ -57,6 +57,6 @@ return error; } -lldb::OptionValueSP OptionValueFormat::DeepCopy() const { - return OptionValueSP(new OptionValueFormat(*this)); +lldb::OptionValueSP OptionValueFormat::Clone() const { + return std::make_shared<OptionValueFormat>(*this); } Index: lldb/source/Interpreter/OptionValueFileSpecList.cpp =================================================================== --- lldb/source/Interpreter/OptionValueFileSpecList.cpp +++ lldb/source/Interpreter/OptionValueFileSpecList.cpp @@ -164,7 +164,7 @@ return error; } -lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const { +OptionValueSP OptionValueFileSpecList::Clone() const { std::lock_guard<std::recursive_mutex> lock(m_mutex); - return OptionValueSP(new OptionValueFileSpecList(m_current_value)); + return std::make_shared<OptionValueFileSpecList>(*this); } Index: lldb/source/Interpreter/OptionValueFileSpec.cpp =================================================================== --- lldb/source/Interpreter/OptionValueFileSpec.cpp +++ lldb/source/Interpreter/OptionValueFileSpec.cpp @@ -88,8 +88,8 @@ return error; } -lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const { - return OptionValueSP(new OptionValueFileSpec(*this)); +lldb::OptionValueSP OptionValueFileSpec::Clone() const { + return std::make_shared<OptionValueFileSpec>(*this); } void OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueFileColonLine.cpp =================================================================== --- lldb/source/Interpreter/OptionValueFileColonLine.cpp +++ lldb/source/Interpreter/OptionValueFileColonLine.cpp @@ -134,8 +134,8 @@ return error; } -lldb::OptionValueSP OptionValueFileColonLine::DeepCopy() const { - return OptionValueSP(new OptionValueFileColonLine(*this)); +lldb::OptionValueSP OptionValueFileColonLine::Clone() const { + return std::make_shared<OptionValueFileColonLine>(*this); } void OptionValueFileColonLine::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueEnumeration.cpp =================================================================== --- lldb/source/Interpreter/OptionValueEnumeration.cpp +++ lldb/source/Interpreter/OptionValueEnumeration.cpp @@ -98,8 +98,8 @@ m_enumerations.Sort(); } -lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const { - return OptionValueSP(new OptionValueEnumeration(*this)); +lldb::OptionValueSP OptionValueEnumeration::Clone() const { + return std::make_shared<OptionValueEnumeration>(*this); } void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueDictionary.cpp =================================================================== --- lldb/source/Interpreter/OptionValueDictionary.cpp +++ lldb/source/Interpreter/OptionValueDictionary.cpp @@ -311,15 +311,20 @@ return false; } -lldb::OptionValueSP OptionValueDictionary::DeepCopy() const { - OptionValueDictionary *copied_dict = - new OptionValueDictionary(m_type_mask, m_raw_value_dump); - lldb::OptionValueSP copied_value_sp(copied_dict); - collection::const_iterator pos, end = m_values.end(); - for (pos = m_values.begin(); pos != end; ++pos) { - StreamString strm; - strm.Printf("%s=", pos->first.GetCString()); - copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true); - } - return copied_value_sp; +OptionValueSP OptionValueDictionary::Clone() const { + return std::make_shared<OptionValueDictionary>(*this); +} + +OptionValueSP +OptionValueDictionary::DeepCopy(const OptionValueSP &new_parent) const { + auto copy_sp = OptionValue::DeepCopy(new_parent); + // copy_sp->GetAsDictionary cannot be used here as it doesn't work for derived + // types that override GetType returning a different value. + auto *dict_value_ptr = static_cast<OptionValueDictionary*>(copy_sp.get()); + lldbassert(dict_value_ptr); + + for (auto &value : dict_value_ptr->m_values) + value.second = value.second->DeepCopy(copy_sp); + + return copy_sp; } Index: lldb/source/Interpreter/OptionValueChar.cpp =================================================================== --- lldb/source/Interpreter/OptionValueChar.cpp +++ lldb/source/Interpreter/OptionValueChar.cpp @@ -58,6 +58,6 @@ return error; } -lldb::OptionValueSP OptionValueChar::DeepCopy() const { - return OptionValueSP(new OptionValueChar(*this)); +OptionValueSP OptionValueChar::Clone() const { + return std::make_shared<OptionValueChar>(*this); } Index: lldb/source/Interpreter/OptionValueBoolean.cpp =================================================================== --- lldb/source/Interpreter/OptionValueBoolean.cpp +++ lldb/source/Interpreter/OptionValueBoolean.cpp @@ -67,8 +67,8 @@ return error; } -lldb::OptionValueSP OptionValueBoolean::DeepCopy() const { - return OptionValueSP(new OptionValueBoolean(*this)); +lldb::OptionValueSP OptionValueBoolean::Clone() const { + return std::make_shared<OptionValueBoolean>(*this); } void OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValueArray.cpp =================================================================== --- lldb/source/Interpreter/OptionValueArray.cpp +++ lldb/source/Interpreter/OptionValueArray.cpp @@ -303,15 +303,20 @@ return error; } -lldb::OptionValueSP OptionValueArray::DeepCopy() const { - OptionValueArray *copied_array = - new OptionValueArray(m_type_mask, m_raw_value_dump); - lldb::OptionValueSP copied_value_sp(copied_array); - *static_cast<OptionValue *>(copied_array) = *this; - copied_array->m_callback = m_callback; - const uint32_t size = m_values.size(); - for (uint32_t i = 0; i < size; ++i) { - copied_array->AppendValue(m_values[i]->DeepCopy()); - } - return copied_value_sp; +OptionValueSP OptionValueArray::Clone() const { + return std::make_shared<OptionValueArray>(*this); +} + +OptionValueSP +OptionValueArray::DeepCopy(const OptionValueSP &new_parent) const { + auto copy_sp = OptionValue::DeepCopy(new_parent); + // copy_sp->GetAsArray cannot be used here as it doesn't work for derived + // types that override GetType returning a different value. + auto *array_value_ptr = static_cast<OptionValueArray *>(copy_sp.get()); + lldbassert(array_value_ptr); + + for (auto &value : array_value_ptr->m_values) + value = value->DeepCopy(copy_sp); + + return copy_sp; } Index: lldb/source/Interpreter/OptionValueArgs.cpp =================================================================== --- lldb/source/Interpreter/OptionValueArgs.cpp +++ lldb/source/Interpreter/OptionValueArgs.cpp @@ -13,9 +13,9 @@ using namespace lldb; using namespace lldb_private; -size_t OptionValueArgs::GetArgs(Args &args) { +size_t OptionValueArgs::GetArgs(Args &args) const { args.Clear(); - for (auto value : m_values) { + for (const auto &value : m_values) { llvm::StringRef string_value = value->GetStringValue(); if (!string_value.empty()) args.AppendArgument(string_value); @@ -23,3 +23,7 @@ return args.GetArgumentCount(); } + +OptionValueSP OptionValueArgs::Clone() const { + return std::make_shared<OptionValueArgs>(*this); +} Index: lldb/source/Interpreter/OptionValueArch.cpp =================================================================== --- lldb/source/Interpreter/OptionValueArch.cpp +++ lldb/source/Interpreter/OptionValueArch.cpp @@ -64,8 +64,8 @@ return error; } -lldb::OptionValueSP OptionValueArch::DeepCopy() const { - return OptionValueSP(new OptionValueArch(*this)); +lldb::OptionValueSP OptionValueArch::Clone() const { + return std::make_shared<OptionValueArch>(*this); } void OptionValueArch::AutoComplete(CommandInterpreter &interpreter, Index: lldb/source/Interpreter/OptionValue.cpp =================================================================== --- lldb/source/Interpreter/OptionValue.cpp +++ lldb/source/Interpreter/OptionValue.cpp @@ -568,6 +568,12 @@ return dumped_something; } +OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const { + auto &&clone = Clone(); + clone->SetParent(new_parent); + return clone; +} + void OptionValue::AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) {} Index: lldb/include/lldb/Target/Target.h =================================================================== --- lldb/include/lldb/Target/Target.h +++ lldb/include/lldb/Target/Target.h @@ -211,7 +211,7 @@ void SetDisplayRecognizedArguments(bool b); - const ProcessLaunchInfo &GetProcessLaunchInfo(); + const ProcessLaunchInfo &GetProcessLaunchInfo() const; void SetProcessLaunchInfo(const ProcessLaunchInfo &launch_info); Index: lldb/include/lldb/Interpreter/OptionValueUUID.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueUUID.h +++ lldb/include/lldb/Interpreter/OptionValueUUID.h @@ -41,8 +41,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions UUID &GetCurrentValue() { return m_uuid; } @@ -55,6 +53,8 @@ CompletionRequest &request) override; protected: + lldb::OptionValueSP Clone() const override; + UUID m_uuid; }; Index: lldb/include/lldb/Interpreter/OptionValueUInt64.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueUInt64.h +++ lldb/include/lldb/Interpreter/OptionValueUInt64.h @@ -52,8 +52,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions const uint64_t &operator=(uint64_t value) { @@ -72,6 +70,8 @@ void SetDefaultValue(uint64_t value) { m_default_value = value; } protected: + lldb::OptionValueSP Clone() const override; + uint64_t m_current_value; uint64_t m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValueString.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueString.h +++ lldb/include/lldb/Interpreter/OptionValueString.h @@ -90,8 +90,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions Flags &GetOptions() { return m_options; } @@ -126,6 +124,8 @@ bool IsDefaultValueEmpty() const { return m_default_value.empty(); } protected: + lldb::OptionValueSP Clone() const override; + std::string m_current_value; std::string m_default_value; Flags m_options; Index: lldb/include/lldb/Interpreter/OptionValueSInt64.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueSInt64.h +++ lldb/include/lldb/Interpreter/OptionValueSInt64.h @@ -55,8 +55,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions const int64_t &operator=(int64_t value) { @@ -93,6 +91,8 @@ int64_t GetMaximumValue() const { return m_max_value; } protected: + lldb::OptionValueSP Clone() const override; + int64_t m_current_value; int64_t m_default_value; int64_t m_min_value; Index: lldb/include/lldb/Interpreter/OptionValueRegex.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueRegex.h +++ lldb/include/lldb/Interpreter/OptionValueRegex.h @@ -41,8 +41,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions const RegularExpression *GetCurrentValue() const { return (m_regex.IsValid() ? &m_regex : nullptr); @@ -58,6 +56,8 @@ bool IsValid() const { return m_regex.IsValid(); } protected: + lldb::OptionValueSP Clone() const override; + RegularExpression m_regex; std::string m_default_regex_str; }; Index: lldb/include/lldb/Interpreter/OptionValueProperties.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueProperties.h +++ lldb/include/lldb/Interpreter/OptionValueProperties.h @@ -18,25 +18,27 @@ #include "lldb/Utility/ConstString.h" namespace lldb_private { +class Properties; class OptionValueProperties : public OptionValue, public std::enable_shared_from_this<OptionValueProperties> { public: - OptionValueProperties() - : OptionValue(), m_name(), m_properties(), m_name_to_index() {} + OptionValueProperties() = default; OptionValueProperties(ConstString name); - OptionValueProperties(const OptionValueProperties &global_properties); - ~OptionValueProperties() override = default; Type GetType() const override { return eTypeProperties; } void Clear() override; - lldb::OptionValueSP DeepCopy() const override; + static lldb::OptionValuePropertiesSP + CreateLocalCopy(const Properties &global_properties); + + lldb::OptionValueSP + DeepCopy(const lldb::OptionValueSP &new_parent) const override; Status SetValueFromString(llvm::StringRef value, @@ -204,6 +206,8 @@ return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr); } + lldb::OptionValueSP Clone() const override; + typedef UniqueCStringMap<size_t> NameToIndex; ConstString m_name; Index: lldb/include/lldb/Interpreter/OptionValuePathMappings.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValuePathMappings.h +++ lldb/include/lldb/Interpreter/OptionValuePathMappings.h @@ -40,8 +40,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - bool IsAggregateValue() const override { return true; } // Subclass specific functions @@ -51,6 +49,8 @@ const PathMappingList &GetCurrentValue() const { return m_path_mappings; } protected: + lldb::OptionValueSP Clone() const override; + PathMappingList m_path_mappings; bool m_notify_changes; }; Index: lldb/include/lldb/Interpreter/OptionValueLanguage.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueLanguage.h +++ lldb/include/lldb/Interpreter/OptionValueLanguage.h @@ -46,8 +46,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions lldb::LanguageType GetCurrentValue() const { return m_current_value; } @@ -59,6 +57,8 @@ void SetDefaultValue(lldb::LanguageType value) { m_default_value = value; } protected: + lldb::OptionValueSP Clone() const override; + lldb::LanguageType m_current_value; lldb::LanguageType m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValueFormatEntity.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueFormatEntity.h +++ lldb/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -36,8 +36,6 @@ void Clear() override; - lldb::OptionValueSP DeepCopy() const override; - void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; @@ -56,6 +54,8 @@ const FormatEntity::Entry &GetDefaultValue() const { return m_default_entry; } protected: + lldb::OptionValueSP Clone() const override; + std::string m_current_format; std::string m_default_format; FormatEntity::Entry m_current_entry; Index: lldb/include/lldb/Interpreter/OptionValueFormat.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueFormat.h +++ lldb/include/lldb/Interpreter/OptionValueFormat.h @@ -43,8 +43,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - // Subclass specific functions lldb::Format GetCurrentValue() const { return m_current_value; } @@ -56,6 +54,8 @@ void SetDefaultValue(lldb::Format value) { m_default_value = value; } protected: + lldb::OptionValueSP Clone() const override; + lldb::Format m_current_value; lldb::Format m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValueFileSpecList.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueFileSpecList.h +++ lldb/include/lldb/Interpreter/OptionValueFileSpecList.h @@ -18,12 +18,12 @@ class OptionValueFileSpecList : public OptionValue { public: - OptionValueFileSpecList() : OptionValue(), m_current_value() {} + OptionValueFileSpecList() = default; - OptionValueFileSpecList(const FileSpecList ¤t_value) - : OptionValue(), m_current_value(current_value) {} + OptionValueFileSpecList(const OptionValueFileSpecList &other) + : OptionValue(other), m_current_value(other.GetCurrentValue()) {} - ~OptionValueFileSpecList() override {} + ~OptionValueFileSpecList() override = default; // Virtual subclass pure virtual overrides @@ -45,8 +45,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - bool IsAggregateValue() const override { return true; } // Subclass specific functions @@ -67,6 +65,8 @@ } protected: + lldb::OptionValueSP Clone() const override; + mutable std::recursive_mutex m_mutex; FileSpecList m_current_value; }; Index: lldb/include/lldb/Interpreter/OptionValueFileSpec.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueFileSpec.h +++ lldb/include/lldb/Interpreter/OptionValueFileSpec.h @@ -48,8 +48,6 @@ m_data_mod_time = llvm::sys::TimePoint<>(); } - lldb::OptionValueSP DeepCopy() const override; - void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; @@ -75,6 +73,8 @@ void SetCompletionMask(uint32_t mask) { m_completion_mask = mask; } protected: + lldb::OptionValueSP Clone() const override; + FileSpec m_current_value; FileSpec m_default_value; lldb::DataBufferSP m_data_sp; Index: lldb/include/lldb/Interpreter/OptionValueFileColonLine.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueFileColonLine.h +++ lldb/include/lldb/Interpreter/OptionValueFileColonLine.h @@ -41,8 +41,6 @@ m_column_number = LLDB_INVALID_COLUMN_NUMBER; } - lldb::OptionValueSP DeepCopy() const override; - void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; @@ -53,6 +51,8 @@ void SetCompletionMask(uint32_t mask) { m_completion_mask = mask; } protected: + lldb::OptionValueSP Clone() const override; + FileSpec m_file_spec; uint32_t m_line_number; uint32_t m_column_number; Index: lldb/include/lldb/Interpreter/OptionValueEnumeration.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueEnumeration.h +++ lldb/include/lldb/Interpreter/OptionValueEnumeration.h @@ -52,8 +52,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; @@ -75,6 +73,8 @@ protected: void SetEnumerations(const OptionEnumValues &enumerators); + lldb::OptionValueSP Clone() const override; + enum_type m_current_value; enum_type m_default_value; EnumerationMap m_enumerations; Index: lldb/include/lldb/Interpreter/OptionValueDictionary.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueDictionary.h +++ lldb/include/lldb/Interpreter/OptionValueDictionary.h @@ -40,7 +40,8 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; + lldb::OptionValueSP + DeepCopy(const lldb::OptionValueSP &new_parent) const override; bool IsAggregateValue() const override { return true; } @@ -72,6 +73,8 @@ Status SetArgs(const Args &args, VarSetOperationType op); protected: + lldb::OptionValueSP Clone() const override; + typedef std::map<ConstString, lldb::OptionValueSP> collection; uint32_t m_type_mask; collection m_values; Index: lldb/include/lldb/Interpreter/OptionValueChar.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueChar.h +++ lldb/include/lldb/Interpreter/OptionValueChar.h @@ -58,9 +58,9 @@ void SetDefaultValue(char value) { m_default_value = value; } - lldb::OptionValueSP DeepCopy() const override; - protected: + lldb::OptionValueSP Clone() const override; + char m_current_value; char m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValueBoolean.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueBoolean.h +++ lldb/include/lldb/Interpreter/OptionValueBoolean.h @@ -75,9 +75,9 @@ void SetDefaultValue(bool value) { m_default_value = value; } - lldb::OptionValueSP DeepCopy() const override; - protected: + lldb::OptionValueSP Clone() const override; + bool m_current_value; bool m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValueArray.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueArray.h +++ lldb/include/lldb/Interpreter/OptionValueArray.h @@ -41,7 +41,8 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; + lldb::OptionValueSP + DeepCopy(const lldb::OptionValueSP &new_parent) const override; bool IsAggregateValue() const override { return true; } @@ -115,6 +116,8 @@ Status SetArgs(const Args &args, VarSetOperationType op); protected: + lldb::OptionValueSP Clone() const override; + typedef std::vector<lldb::OptionValueSP> collection; uint32_t m_type_mask; Index: lldb/include/lldb/Interpreter/OptionValueArgs.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueArgs.h +++ lldb/include/lldb/Interpreter/OptionValueArgs.h @@ -19,11 +19,14 @@ : OptionValueArray( OptionValue::ConvertTypeToMask(OptionValue::eTypeString)) {} - ~OptionValueArgs() override {} + ~OptionValueArgs() override = default; - size_t GetArgs(Args &args); + size_t GetArgs(Args &args) const; Type GetType() const override { return eTypeArgs; } + +protected: + lldb::OptionValueSP Clone() const override; }; } // namespace lldb_private Index: lldb/include/lldb/Interpreter/OptionValueArch.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValueArch.h +++ lldb/include/lldb/Interpreter/OptionValueArch.h @@ -52,8 +52,6 @@ m_value_was_set = false; } - lldb::OptionValueSP DeepCopy() const override; - void AutoComplete(CommandInterpreter &interpreter, lldb_private::CompletionRequest &request) override; @@ -74,6 +72,8 @@ void SetDefaultValue(const ArchSpec &value) { m_default_value = value; } protected: + lldb::OptionValueSP Clone() const override; + ArchSpec m_current_value; ArchSpec m_default_value; }; Index: lldb/include/lldb/Interpreter/OptionValue.h =================================================================== --- lldb/include/lldb/Interpreter/OptionValue.h +++ lldb/include/lldb/Interpreter/OptionValue.h @@ -87,7 +87,8 @@ virtual void Clear() = 0; - virtual lldb::OptionValueSP DeepCopy() const = 0; + virtual lldb::OptionValueSP + DeepCopy(const lldb::OptionValueSP &new_parent) const; virtual void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request); @@ -306,6 +307,10 @@ m_parent_wp = parent_sp; } + lldb::OptionValueSP GetParent() const { + return m_parent_wp.lock(); + } + void SetValueChangedCallback(std::function<void()> callback) { assert(!m_callback); m_callback = std::move(callback); @@ -317,6 +322,10 @@ } protected: + // Must be overriden by a derived class for correct downcasting the result of + // DeepCopy to it. + virtual lldb::OptionValueSP Clone() const = 0; + lldb::OptionValueWP m_parent_wp; std::function<void()> m_callback; bool m_value_was_set; // This can be used to see if a value has been set
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits