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 &current_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

Reply via email to