[Lldb-commits] [lldb] f0f183e - [lldb/Interpreter] Fix deep copying for OptionValue classes
Tatyana Krasnukha via lldb-commits
lldb-commits at lists.llvm.org
Sun Feb 28 08:24:28 PST 2021
Author: Tatyana Krasnukha
Date: 2021-02-28T19:23:25+03:00
New Revision: f0f183ee4ad952d94234cf6971c69a044e05c9df
URL: https://github.com/llvm/llvm-project/commit/f0f183ee4ad952d94234cf6971c69a044e05c9df
DIFF: https://github.com/llvm/llvm-project/commit/f0f183ee4ad952d94234cf6971c69a044e05c9df.diff
LOG: [lldb/Interpreter] Fix deep copying for OptionValue classes
Some implementations of the DeepCopy function called the copy constructor that copied m_parent member instead of setting a new parent. Others just leaved 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.
The patch implements idiom "virtual constructor" to fix these issues.
Add a test that checks DeepCopy for correct copying/setting all data members of the base class.
Differential Revision: https://reviews.llvm.org/D96952
Added:
lldb/include/lldb/Utility/Cloneable.h
lldb/unittests/Interpreter/TestOptionValue.cpp
Modified:
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/source/Interpreter/OptionValue.cpp
lldb/source/Interpreter/OptionValueArch.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
Removed:
################################################################################
diff --git a/lldb/include/lldb/Interpreter/OptionValue.h b/lldb/include/lldb/Interpreter/OptionValue.h
index a8176e39940a..218fa6f029c1 100644
--- a/lldb/include/lldb/Interpreter/OptionValue.h
+++ b/lldb/include/lldb/Interpreter/OptionValue.h
@@ -10,6 +10,7 @@
#define LLDB_INTERPRETER_OPTIONVALUE_H
#include "lldb/Core/FormatEntity.h"
+#include "lldb/Utility/Cloneable.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
@@ -87,7 +88,8 @@ class OptionValue {
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 +308,8 @@ class OptionValue {
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 +321,12 @@ class OptionValue {
}
protected:
+ using TopmostBase = OptionValue;
+
+ // Must be overriden by a derived class for correct downcasting the result of
+ // DeepCopy to it. Inherit from Cloneable to avoid doing this manually.
+ 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
diff --git a/lldb/include/lldb/Interpreter/OptionValueArch.h b/lldb/include/lldb/Interpreter/OptionValueArch.h
index 22f75a6259c5..e17520879447 100644
--- a/lldb/include/lldb/Interpreter/OptionValueArch.h
+++ b/lldb/include/lldb/Interpreter/OptionValueArch.h
@@ -15,7 +15,7 @@
namespace lldb_private {
-class OptionValueArch : public OptionValue {
+class OptionValueArch : public Cloneable<OptionValueArch, OptionValue> {
public:
OptionValueArch() = default;
@@ -47,8 +47,6 @@ class OptionValueArch : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
void AutoComplete(CommandInterpreter &interpreter,
lldb_private::CompletionRequest &request) override;
diff --git a/lldb/include/lldb/Interpreter/OptionValueArgs.h b/lldb/include/lldb/Interpreter/OptionValueArgs.h
index 8cea8ced74de..1e2a1430d0c5 100644
--- a/lldb/include/lldb/Interpreter/OptionValueArgs.h
+++ b/lldb/include/lldb/Interpreter/OptionValueArgs.h
@@ -13,11 +13,10 @@
namespace lldb_private {
-class OptionValueArgs : public OptionValueArray {
+class OptionValueArgs : public Cloneable<OptionValueArgs, OptionValueArray> {
public:
OptionValueArgs()
- : OptionValueArray(
- OptionValue::ConvertTypeToMask(OptionValue::eTypeString)) {}
+ : Cloneable(OptionValue::ConvertTypeToMask(OptionValue::eTypeString)) {}
~OptionValueArgs() override = default;
diff --git a/lldb/include/lldb/Interpreter/OptionValueArray.h b/lldb/include/lldb/Interpreter/OptionValueArray.h
index 44bde8ee8699..011eefc34251 100644
--- a/lldb/include/lldb/Interpreter/OptionValueArray.h
+++ b/lldb/include/lldb/Interpreter/OptionValueArray.h
@@ -15,7 +15,7 @@
namespace lldb_private {
-class OptionValueArray : public OptionValue {
+class OptionValueArray : public Cloneable<OptionValueArray, OptionValue> {
public:
OptionValueArray(uint32_t type_mask = UINT32_MAX, bool raw_value_dump = false)
: m_type_mask(type_mask), m_values(), m_raw_value_dump(raw_value_dump) {}
@@ -38,7 +38,8 @@ class OptionValueArray : public OptionValue {
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; }
diff --git a/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/lldb/include/lldb/Interpreter/OptionValueBoolean.h
index 6ae464bd8fb2..fd15ccb12c40 100644
--- a/lldb/include/lldb/Interpreter/OptionValueBoolean.h
+++ b/lldb/include/lldb/Interpreter/OptionValueBoolean.h
@@ -13,7 +13,7 @@
namespace lldb_private {
-class OptionValueBoolean : public OptionValue {
+class OptionValueBoolean : public Cloneable<OptionValueBoolean, OptionValue> {
public:
OptionValueBoolean(bool value)
: m_current_value(value), m_default_value(value) {}
@@ -71,8 +71,6 @@ class OptionValueBoolean : public OptionValue {
void SetDefaultValue(bool value) { m_default_value = value; }
- lldb::OptionValueSP DeepCopy() const override;
-
protected:
bool m_current_value;
bool m_default_value;
diff --git a/lldb/include/lldb/Interpreter/OptionValueChar.h b/lldb/include/lldb/Interpreter/OptionValueChar.h
index 78f91df99842..6b8a314a7c99 100644
--- a/lldb/include/lldb/Interpreter/OptionValueChar.h
+++ b/lldb/include/lldb/Interpreter/OptionValueChar.h
@@ -13,7 +13,7 @@
namespace lldb_private {
-class OptionValueChar : public OptionValue {
+class OptionValueChar : public Cloneable<OptionValueChar, OptionValue> {
public:
OptionValueChar(char value)
: m_current_value(value), m_default_value(value) {}
@@ -54,8 +54,6 @@ class OptionValueChar : public OptionValue {
void SetDefaultValue(char value) { m_default_value = value; }
- lldb::OptionValueSP DeepCopy() const override;
-
protected:
char m_current_value;
char m_default_value;
diff --git a/lldb/include/lldb/Interpreter/OptionValueDictionary.h b/lldb/include/lldb/Interpreter/OptionValueDictionary.h
index f1538983b50b..f96cbc9fe9e7 100644
--- a/lldb/include/lldb/Interpreter/OptionValueDictionary.h
+++ b/lldb/include/lldb/Interpreter/OptionValueDictionary.h
@@ -15,7 +15,8 @@
namespace lldb_private {
-class OptionValueDictionary : public OptionValue {
+class OptionValueDictionary
+ : public Cloneable<OptionValueDictionary, OptionValue> {
public:
OptionValueDictionary(uint32_t type_mask = UINT32_MAX,
bool raw_value_dump = true)
@@ -39,7 +40,8 @@ class OptionValueDictionary : public OptionValue {
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; }
diff --git a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
index 0fe70193dece..7dc6eea4e69d 100644
--- a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
+++ b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
@@ -19,7 +19,8 @@
namespace lldb_private {
-class OptionValueEnumeration : public OptionValue {
+class OptionValueEnumeration
+ : public Cloneable<OptionValueEnumeration, OptionValue> {
public:
typedef int64_t enum_type;
struct EnumeratorInfo {
@@ -49,8 +50,6 @@ class OptionValueEnumeration : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
void AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) override;
diff --git a/lldb/include/lldb/Interpreter/OptionValueFileColonLine.h b/lldb/include/lldb/Interpreter/OptionValueFileColonLine.h
index 86fd0d5aec2c..80a38fc9ed7e 100644
--- a/lldb/include/lldb/Interpreter/OptionValueFileColonLine.h
+++ b/lldb/include/lldb/Interpreter/OptionValueFileColonLine.h
@@ -16,7 +16,8 @@
namespace lldb_private {
-class OptionValueFileColonLine : public OptionValue {
+class OptionValueFileColonLine :
+ public Cloneable<OptionValueFileColonLine, OptionValue> {
public:
OptionValueFileColonLine();
OptionValueFileColonLine(const llvm::StringRef input);
@@ -38,8 +39,6 @@ class OptionValueFileColonLine : public OptionValue {
m_column_number = LLDB_INVALID_COLUMN_NUMBER;
}
- lldb::OptionValueSP DeepCopy() const override;
-
void AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) override;
diff --git a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
index 4168e4b1b542..dbaeac6c60c1 100644
--- a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
+++ b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
@@ -16,7 +16,7 @@
namespace lldb_private {
-class OptionValueFileSpec : public OptionValue {
+class OptionValueFileSpec : public Cloneable<OptionValueFileSpec, OptionValue> {
public:
OptionValueFileSpec(bool resolve = true);
@@ -45,8 +45,6 @@ class OptionValueFileSpec : public OptionValue {
m_data_mod_time = llvm::sys::TimePoint<>();
}
- lldb::OptionValueSP DeepCopy() const override;
-
void AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) override;
diff --git a/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h b/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
index 73c8058402e3..29641c3a2087 100644
--- a/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
+++ b/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
@@ -16,12 +16,13 @@
namespace lldb_private {
-class OptionValueFileSpecList : public OptionValue {
+class OptionValueFileSpecList
+ : public Cloneable<OptionValueFileSpecList, OptionValue> {
public:
OptionValueFileSpecList() = default;
- OptionValueFileSpecList(const FileSpecList ¤t_value)
- : m_current_value(current_value) {}
+ OptionValueFileSpecList(const OptionValueFileSpecList &other)
+ : Cloneable(other), m_current_value(other.GetCurrentValue()) {}
~OptionValueFileSpecList() override = default;
@@ -42,8 +43,6 @@ class OptionValueFileSpecList : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
bool IsAggregateValue() const override { return true; }
// Subclass specific functions
@@ -64,6 +63,8 @@ class OptionValueFileSpecList : public OptionValue {
}
protected:
+ lldb::OptionValueSP Clone() const override;
+
mutable std::recursive_mutex m_mutex;
FileSpecList m_current_value;
};
diff --git a/lldb/include/lldb/Interpreter/OptionValueFormat.h b/lldb/include/lldb/Interpreter/OptionValueFormat.h
index aa5ec591a533..1f2c66b164d5 100644
--- a/lldb/include/lldb/Interpreter/OptionValueFormat.h
+++ b/lldb/include/lldb/Interpreter/OptionValueFormat.h
@@ -13,7 +13,8 @@
namespace lldb_private {
-class OptionValueFormat : public OptionValue {
+class OptionValueFormat
+ : public Cloneable<OptionValueFormat, OptionValue> {
public:
OptionValueFormat(lldb::Format value)
: m_current_value(value), m_default_value(value) {}
@@ -39,8 +40,6 @@ class OptionValueFormat : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
lldb::Format GetCurrentValue() const { return m_current_value; }
diff --git a/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
index 4100ee2bc2ef..cb8b2ef13fa4 100644
--- a/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
+++ b/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
@@ -14,7 +14,8 @@
namespace lldb_private {
-class OptionValueFormatEntity : public OptionValue {
+class OptionValueFormatEntity
+ : public Cloneable<OptionValueFormatEntity, OptionValue> {
public:
OptionValueFormatEntity(const char *default_format);
@@ -33,8 +34,6 @@ class OptionValueFormatEntity : public OptionValue {
void Clear() override;
- lldb::OptionValueSP DeepCopy() const override;
-
void AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) override;
diff --git a/lldb/include/lldb/Interpreter/OptionValueLanguage.h b/lldb/include/lldb/Interpreter/OptionValueLanguage.h
index 44f5eaab9b42..c00f71ffff33 100644
--- a/lldb/include/lldb/Interpreter/OptionValueLanguage.h
+++ b/lldb/include/lldb/Interpreter/OptionValueLanguage.h
@@ -15,7 +15,7 @@
namespace lldb_private {
-class OptionValueLanguage : public OptionValue {
+class OptionValueLanguage : public Cloneable<OptionValueLanguage, OptionValue> {
public:
OptionValueLanguage(lldb::LanguageType value)
: m_current_value(value), m_default_value(value) {}
@@ -42,8 +42,6 @@ class OptionValueLanguage : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
lldb::LanguageType GetCurrentValue() const { return m_current_value; }
diff --git a/lldb/include/lldb/Interpreter/OptionValuePathMappings.h b/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
index 3f23246634f5..4bc65ce76c76 100644
--- a/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
+++ b/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
@@ -14,7 +14,8 @@
namespace lldb_private {
-class OptionValuePathMappings : public OptionValue {
+class OptionValuePathMappings
+ : public Cloneable<OptionValuePathMappings, OptionValue> {
public:
OptionValuePathMappings(bool notify_changes)
: m_notify_changes(notify_changes) {}
@@ -37,8 +38,6 @@ class OptionValuePathMappings : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
bool IsAggregateValue() const override { return true; }
// Subclass specific functions
diff --git a/lldb/include/lldb/Interpreter/OptionValueProperties.h b/lldb/include/lldb/Interpreter/OptionValueProperties.h
index d17f123ce474..6fa5403ac142 100644
--- a/lldb/include/lldb/Interpreter/OptionValueProperties.h
+++ b/lldb/include/lldb/Interpreter/OptionValueProperties.h
@@ -18,24 +18,27 @@
#include "lldb/Utility/ConstString.h"
namespace lldb_private {
+class Properties;
class OptionValueProperties
- : public OptionValue,
+ : public Cloneable<OptionValueProperties, OptionValue>,
public std::enable_shared_from_this<OptionValueProperties> {
public:
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,
diff --git a/lldb/include/lldb/Interpreter/OptionValueRegex.h b/lldb/include/lldb/Interpreter/OptionValueRegex.h
index fbfb789301e8..9eb0247e0405 100644
--- a/lldb/include/lldb/Interpreter/OptionValueRegex.h
+++ b/lldb/include/lldb/Interpreter/OptionValueRegex.h
@@ -14,7 +14,7 @@
namespace lldb_private {
-class OptionValueRegex : public OptionValue {
+class OptionValueRegex : public Cloneable<OptionValueRegex, OptionValue> {
public:
OptionValueRegex(const char *value = nullptr)
: m_regex(llvm::StringRef::withNullAsEmpty(value)),
@@ -38,8 +38,6 @@ class OptionValueRegex : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
const RegularExpression *GetCurrentValue() const {
return (m_regex.IsValid() ? &m_regex : nullptr);
diff --git a/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/lldb/include/lldb/Interpreter/OptionValueSInt64.h
index 54295cb724ff..3493eb1037c0 100644
--- a/lldb/include/lldb/Interpreter/OptionValueSInt64.h
+++ b/lldb/include/lldb/Interpreter/OptionValueSInt64.h
@@ -14,7 +14,7 @@
namespace lldb_private {
-class OptionValueSInt64 : public OptionValue {
+class OptionValueSInt64 : public Cloneable<OptionValueSInt64, OptionValue> {
public:
OptionValueSInt64() = default;
@@ -44,8 +44,6 @@ class OptionValueSInt64 : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
const int64_t &operator=(int64_t value) {
diff --git a/lldb/include/lldb/Interpreter/OptionValueString.h b/lldb/include/lldb/Interpreter/OptionValueString.h
index 948eef7fe4e9..5611b5849097 100644
--- a/lldb/include/lldb/Interpreter/OptionValueString.h
+++ b/lldb/include/lldb/Interpreter/OptionValueString.h
@@ -17,7 +17,7 @@
namespace lldb_private {
-class OptionValueString : public OptionValue {
+class OptionValueString : public Cloneable<OptionValueString, OptionValue> {
public:
typedef Status (*ValidatorCallback)(const char *string, void *baton);
@@ -78,8 +78,6 @@ class OptionValueString : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
Flags &GetOptions() { return m_options; }
diff --git a/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/lldb/include/lldb/Interpreter/OptionValueUInt64.h
index bc21b1a2a89c..f212b2a19def 100644
--- a/lldb/include/lldb/Interpreter/OptionValueUInt64.h
+++ b/lldb/include/lldb/Interpreter/OptionValueUInt64.h
@@ -14,7 +14,7 @@
namespace lldb_private {
-class OptionValueUInt64 : public OptionValue {
+class OptionValueUInt64 : public Cloneable<OptionValueUInt64, OptionValue> {
public:
OptionValueUInt64() = default;
@@ -47,8 +47,6 @@ class OptionValueUInt64 : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
const uint64_t &operator=(uint64_t value) {
diff --git a/lldb/include/lldb/Interpreter/OptionValueUUID.h b/lldb/include/lldb/Interpreter/OptionValueUUID.h
index 2d1d8bdeba61..0ed490d1811d 100644
--- a/lldb/include/lldb/Interpreter/OptionValueUUID.h
+++ b/lldb/include/lldb/Interpreter/OptionValueUUID.h
@@ -14,7 +14,7 @@
namespace lldb_private {
-class OptionValueUUID : public OptionValue {
+class OptionValueUUID : public Cloneable<OptionValueUUID, OptionValue> {
public:
OptionValueUUID() = default;
@@ -38,8 +38,6 @@ class OptionValueUUID : public OptionValue {
m_value_was_set = false;
}
- lldb::OptionValueSP DeepCopy() const override;
-
// Subclass specific functions
UUID &GetCurrentValue() { return m_uuid; }
diff --git a/lldb/include/lldb/Utility/Cloneable.h b/lldb/include/lldb/Utility/Cloneable.h
new file mode 100644
index 000000000000..7082f3a59ce5
--- /dev/null
+++ b/lldb/include/lldb/Utility/Cloneable.h
@@ -0,0 +1,55 @@
+//===-- Cloneable.h ---------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_CLONEABLE_H
+#define LLDB_UTILITY_CLONEABLE_H
+
+#include <type_traits>
+
+namespace lldb_private {
+
+/// \class Cloneable Cloneable.h "lldb/Utility/Cloneable.h"
+/// A class that implements CRTP-based "virtual constructor" idiom.
+///
+/// Example:
+/// @code
+/// class Base {
+/// using TopmostBase = Base;
+/// public:
+/// virtual std::shared_ptr<Base> Clone() const = 0;
+/// };
+/// @endcode
+///
+/// To define a class derived from the Base with overridden Clone:
+/// @code
+/// class Intermediate : public Cloneable<Intermediate, Base> {};
+/// @endcode
+///
+/// To define a class at the next level of inheritance with overridden Clone:
+/// @code
+/// class Derived : public Cloneable<Derived, Intermediate> {};
+/// @endcode
+
+template <typename Derived, typename Base>
+class Cloneable : public Base {
+public:
+ using Base::Base;
+
+ std::shared_ptr<typename Base::TopmostBase> Clone() const override {
+ // std::is_base_of requires derived type to be complete, that's why class
+ // scope static_assert cannot be used.
+ static_assert(std::is_base_of<Cloneable, Derived>::value,
+ "Derived class must be derived from this.");
+
+ return std::make_shared<Derived>(static_cast<const Derived &>(*this));
+ }
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_CLONEABLE_H
diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp
index 0bd9a591af67..350afeb073c4 100644
--- a/lldb/source/Interpreter/OptionValue.cpp
+++ b/lldb/source/Interpreter/OptionValue.cpp
@@ -568,6 +568,12 @@ bool OptionValue::DumpQualifiedName(Stream &strm) const {
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) {}
diff --git a/lldb/source/Interpreter/OptionValueArch.cpp b/lldb/source/Interpreter/OptionValueArch.cpp
index ac78ee64a9d7..4d1e2c7869f3 100644
--- a/lldb/source/Interpreter/OptionValueArch.cpp
+++ b/lldb/source/Interpreter/OptionValueArch.cpp
@@ -64,10 +64,6 @@ Status OptionValueArch::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueArch::DeepCopy() const {
- return OptionValueSP(new OptionValueArch(*this));
-}
-
void OptionValueArch::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueArray.cpp b/lldb/source/Interpreter/OptionValueArray.cpp
index 0b293ccfc248..b1545bdebf10 100644
--- a/lldb/source/Interpreter/OptionValueArray.cpp
+++ b/lldb/source/Interpreter/OptionValueArray.cpp
@@ -303,15 +303,16 @@ Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
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::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
diff erent 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;
}
diff --git a/lldb/source/Interpreter/OptionValueBoolean.cpp b/lldb/source/Interpreter/OptionValueBoolean.cpp
index 24ae3f673bf9..62845c14bd13 100644
--- a/lldb/source/Interpreter/OptionValueBoolean.cpp
+++ b/lldb/source/Interpreter/OptionValueBoolean.cpp
@@ -67,10 +67,6 @@ Status OptionValueBoolean::SetValueFromString(llvm::StringRef value_str,
return error;
}
-lldb::OptionValueSP OptionValueBoolean::DeepCopy() const {
- return OptionValueSP(new OptionValueBoolean(*this));
-}
-
void OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
llvm::StringRef autocomplete_entries[] = {"true", "false", "on", "off",
diff --git a/lldb/source/Interpreter/OptionValueChar.cpp b/lldb/source/Interpreter/OptionValueChar.cpp
index af9a371f46d4..7fe72c9aa221 100644
--- a/lldb/source/Interpreter/OptionValueChar.cpp
+++ b/lldb/source/Interpreter/OptionValueChar.cpp
@@ -57,7 +57,3 @@ Status OptionValueChar::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueChar::DeepCopy() const {
- return OptionValueSP(new OptionValueChar(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueDictionary.cpp b/lldb/source/Interpreter/OptionValueDictionary.cpp
index 79323f502d17..26fed4a987e1 100644
--- a/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -311,15 +311,16 @@ bool OptionValueDictionary::DeleteValueForKey(ConstString key) {
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::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
diff erent 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;
}
diff --git a/lldb/source/Interpreter/OptionValueEnumeration.cpp b/lldb/source/Interpreter/OptionValueEnumeration.cpp
index d216a5c5218d..f75519c577c5 100644
--- a/lldb/source/Interpreter/OptionValueEnumeration.cpp
+++ b/lldb/source/Interpreter/OptionValueEnumeration.cpp
@@ -95,10 +95,6 @@ void OptionValueEnumeration::SetEnumerations(
m_enumerations.Sort();
}
-lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
- return OptionValueSP(new OptionValueEnumeration(*this));
-}
-
void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
const uint32_t num_enumerators = m_enumerations.GetSize();
diff --git a/lldb/source/Interpreter/OptionValueFileColonLine.cpp b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
index 6d5d82d9ed3b..6f954e99f9b0 100644
--- a/lldb/source/Interpreter/OptionValueFileColonLine.cpp
+++ b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
@@ -134,10 +134,6 @@ Status OptionValueFileColonLine::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueFileColonLine::DeepCopy() const {
- return OptionValueSP(new OptionValueFileColonLine(*this));
-}
-
void OptionValueFileColonLine::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueFileSpec.cpp b/lldb/source/Interpreter/OptionValueFileSpec.cpp
index 8d43371f8674..9f80cc86db50 100644
--- a/lldb/source/Interpreter/OptionValueFileSpec.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpec.cpp
@@ -84,10 +84,6 @@ Status OptionValueFileSpec::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const {
- return OptionValueSP(new OptionValueFileSpec(*this));
-}
-
void OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
CommandCompletions::InvokeCommonCompletionCallbacks(
diff --git a/lldb/source/Interpreter/OptionValueFileSpecList.cpp b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
index f2367b1941c9..2160fd61d428 100644
--- a/lldb/source/Interpreter/OptionValueFileSpecList.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpecList.cpp
@@ -164,7 +164,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
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 Cloneable::Clone();
}
diff --git a/lldb/source/Interpreter/OptionValueFormat.cpp b/lldb/source/Interpreter/OptionValueFormat.cpp
index b676bed50e62..76a446d1c3bc 100644
--- a/lldb/source/Interpreter/OptionValueFormat.cpp
+++ b/lldb/source/Interpreter/OptionValueFormat.cpp
@@ -56,7 +56,3 @@ Status OptionValueFormat::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueFormat::DeepCopy() const {
- return OptionValueSP(new OptionValueFormat(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/lldb/source/Interpreter/OptionValueFormatEntity.cpp
index 00d58922f950..64fcaf2cbc85 100644
--- a/lldb/source/Interpreter/OptionValueFormatEntity.cpp
+++ b/lldb/source/Interpreter/OptionValueFormatEntity.cpp
@@ -109,10 +109,6 @@ Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
return error;
}
-lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const {
- return OptionValueSP(new OptionValueFormatEntity(*this));
-}
-
void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
FormatEntity::AutoComplete(request);
diff --git a/lldb/source/Interpreter/OptionValueLanguage.cpp b/lldb/source/Interpreter/OptionValueLanguage.cpp
index 5b310782a1ba..d2fbe248300d 100644
--- a/lldb/source/Interpreter/OptionValueLanguage.cpp
+++ b/lldb/source/Interpreter/OptionValueLanguage.cpp
@@ -69,7 +69,3 @@ Status OptionValueLanguage::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueLanguage::DeepCopy() const {
- return OptionValueSP(new OptionValueLanguage(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValuePathMappings.cpp b/lldb/source/Interpreter/OptionValuePathMappings.cpp
index 3b3f43d07293..4dceb5632716 100644
--- a/lldb/source/Interpreter/OptionValuePathMappings.cpp
+++ b/lldb/source/Interpreter/OptionValuePathMappings.cpp
@@ -196,7 +196,3 @@ Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const {
- return OptionValueSP(new OptionValuePathMappings(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 886af3269a32..c1551bd51a07 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -22,26 +22,6 @@ using namespace lldb_private;
OptionValueProperties::OptionValueProperties(ConstString name) : m_name(name) {}
-OptionValueProperties::OptionValueProperties(
- const OptionValueProperties &global_properties)
- : OptionValue(global_properties),
- 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();
}
@@ -562,8 +542,32 @@ Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
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::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
diff erent 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(
diff --git a/lldb/source/Interpreter/OptionValueRegex.cpp b/lldb/source/Interpreter/OptionValueRegex.cpp
index bec3942d9cb0..bbeca8da7714 100644
--- a/lldb/source/Interpreter/OptionValueRegex.cpp
+++ b/lldb/source/Interpreter/OptionValueRegex.cpp
@@ -59,7 +59,3 @@ Status OptionValueRegex::SetValueFromString(llvm::StringRef value,
}
return error;
}
-
-lldb::OptionValueSP OptionValueRegex::DeepCopy() const {
- return OptionValueSP(new OptionValueRegex(m_regex.GetText().str().c_str()));
-}
diff --git a/lldb/source/Interpreter/OptionValueSInt64.cpp b/lldb/source/Interpreter/OptionValueSInt64.cpp
index ada20b2139a3..b875ba8e3536 100644
--- a/lldb/source/Interpreter/OptionValueSInt64.cpp
+++ b/lldb/source/Interpreter/OptionValueSInt64.cpp
@@ -70,7 +70,3 @@ Status OptionValueSInt64::SetValueFromString(llvm::StringRef value_ref,
}
return error;
}
-
-lldb::OptionValueSP OptionValueSInt64::DeepCopy() const {
- return OptionValueSP(new OptionValueSInt64(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueString.cpp b/lldb/source/Interpreter/OptionValueString.cpp
index 22f5d08bf832..b4fec91bc33f 100644
--- a/lldb/source/Interpreter/OptionValueString.cpp
+++ b/lldb/source/Interpreter/OptionValueString.cpp
@@ -117,10 +117,6 @@ Status OptionValueString::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueString::DeepCopy() const {
- return OptionValueSP(new OptionValueString(*this));
-}
-
Status OptionValueString::SetCurrentValue(llvm::StringRef value) {
if (m_validator) {
Status error(m_validator(value.str().c_str(), m_validator_baton));
diff --git a/lldb/source/Interpreter/OptionValueUInt64.cpp b/lldb/source/Interpreter/OptionValueUInt64.cpp
index 98ef016e5f77..a2751a4d02eb 100644
--- a/lldb/source/Interpreter/OptionValueUInt64.cpp
+++ b/lldb/source/Interpreter/OptionValueUInt64.cpp
@@ -68,7 +68,3 @@ Status OptionValueUInt64::SetValueFromString(llvm::StringRef value_ref,
}
return error;
}
-
-lldb::OptionValueSP OptionValueUInt64::DeepCopy() const {
- return OptionValueSP(new OptionValueUInt64(*this));
-}
diff --git a/lldb/source/Interpreter/OptionValueUUID.cpp b/lldb/source/Interpreter/OptionValueUUID.cpp
index 2bd749773556..283f9c1b67b3 100644
--- a/lldb/source/Interpreter/OptionValueUUID.cpp
+++ b/lldb/source/Interpreter/OptionValueUUID.cpp
@@ -58,10 +58,6 @@ Status OptionValueUUID::SetValueFromString(llvm::StringRef value,
return error;
}
-lldb::OptionValueSP OptionValueUUID::DeepCopy() const {
- return OptionValueSP(new OptionValueUUID(*this));
-}
-
void OptionValueUUID::AutoComplete(CommandInterpreter &interpreter,
CompletionRequest &request) {
ExecutionContext exe_ctx(interpreter.GetExecutionContext());
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index de0ffa7ddd5d..979c649bf6e0 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -83,16 +83,10 @@ using namespace std::chrono;
#define DISABLE_MEM_CACHE_DEFAULT true
#endif
-class ProcessOptionValueProperties : public OptionValueProperties {
+class ProcessOptionValueProperties
+ : public Cloneable<ProcessOptionValueProperties, OptionValueProperties> {
public:
- 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()) {}
+ ProcessOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -131,10 +125,12 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class ProcessExperimentalOptionValueProperties : public OptionValueProperties {
+class ProcessExperimentalOptionValueProperties
+ : public Cloneable<ProcessExperimentalOptionValueProperties,
+ OptionValueProperties> {
public:
ProcessExperimentalOptionValueProperties()
- : OptionValueProperties(
+ : Cloneable(
ConstString(Properties::GetExperimentalSettingsName())) {}
};
@@ -157,8 +153,8 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
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); });
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 38e13e1287bf..6cf9d54c7751 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3615,15 +3615,10 @@ enum {
ePropertyExperimental,
};
-class TargetOptionValueProperties : public OptionValueProperties {
+class TargetOptionValueProperties
+ : public Cloneable<TargetOptionValueProperties, OptionValueProperties> {
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()) {}
+ TargetOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -3654,11 +3649,12 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class TargetExperimentalOptionValueProperties : public OptionValueProperties {
+class TargetExperimentalOptionValueProperties
+ : public Cloneable<TargetExperimentalOptionValueProperties,
+ OptionValueProperties> {
public:
TargetExperimentalOptionValueProperties()
- : OptionValueProperties(
- ConstString(Properties::GetExperimentalSettingsName())) {}
+ : Cloneable(ConstString(Properties::GetExperimentalSettingsName())) {}
};
TargetExperimentalProperties::TargetExperimentalProperties()
@@ -3671,8 +3667,8 @@ TargetExperimentalProperties::TargetExperimentalProperties()
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
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 854f7e81153e..e261cae4bd8a 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -71,16 +71,10 @@ enum {
#include "TargetPropertiesEnum.inc"
};
-class ThreadOptionValueProperties : public OptionValueProperties {
+class ThreadOptionValueProperties
+ : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> {
public:
- 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()) {}
+ ThreadOptionValueProperties(ConstString name) : Cloneable(name) {}
const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
bool will_modify,
@@ -108,8 +102,8 @@ ThreadProperties::ThreadProperties(bool is_global) : Properties() {
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;
diff --git a/lldb/test/API/commands/settings/TestSettings.py b/lldb/test/API/commands/settings/TestSettings.py
index 180d45e4e934..c3cfdabe75de 100644
--- a/lldb/test/API/commands/settings/TestSettings.py
+++ b/lldb/test/API/commands/settings/TestSettings.py
@@ -238,6 +238,11 @@ def do_test_run_args_and_env_vars(self, use_launchsimple):
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"])
diff --git a/lldb/unittests/Interpreter/CMakeLists.txt b/lldb/unittests/Interpreter/CMakeLists.txt
index 28663ec02a2a..6ea5996e2b03 100644
--- a/lldb/unittests/Interpreter/CMakeLists.txt
+++ b/lldb/unittests/Interpreter/CMakeLists.txt
@@ -1,6 +1,7 @@
add_lldb_unittest(InterpreterTests
TestCompletion.cpp
TestOptionArgParser.cpp
+ TestOptionValue.cpp
TestOptionValueFileColonLine.cpp
LINK_LIBS
diff --git a/lldb/unittests/Interpreter/TestOptionValue.cpp b/lldb/unittests/Interpreter/TestOptionValue.cpp
new file mode 100644
index 000000000000..a059b9c67eaa
--- /dev/null
+++ b/lldb/unittests/Interpreter/TestOptionValue.cpp
@@ -0,0 +1,173 @@
+//===-- 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("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("c", eVarSetOperationAppend);
+ ASSERT_EQ(copy_sp->GetStringValue(), "abc");
+}
+
+// Test an aggregate class.
+TEST(OptionValueArgs, DeepCopy) {
+ OptionValueArgs args;
+ args.SetValueFromString("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("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("A=1 B=2");
+ props_sp->GetFileList()->SetValueFromString("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(), 1U);
+
+ 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(), 2U);
+
+ // 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("C=3", eVarSetOperationAppend);
+
+ // Trigger the callback second time.
+ file_list_copy_ptr->SetValueFromString("0 another/path", eVarSetOperationReplace);
+}
More information about the lldb-commits
mailing list