diff --git a/lib/include/pl/api.hpp b/lib/include/pl/api.hpp index f90bbf0d..6317692b 100644 --- a/lib/include/pl/api.hpp +++ b/lib/include/pl/api.hpp @@ -126,7 +126,7 @@ namespace pl::api { /** * @brief A function callback called when a custom built-in type is being instantiated */ - using TypeCallback = std::function(core::Evaluator *, const std::vector &)>; + using TypeCallback = std::function(core::Evaluator *, const std::vector &)>; /** * @brief A type representing a function. diff --git a/lib/include/pl/helpers/create_shared_object.hpp b/lib/include/pl/helpers/create_shared_object.hpp new file mode 100644 index 00000000..947449b0 --- /dev/null +++ b/lib/include/pl/helpers/create_shared_object.hpp @@ -0,0 +1,131 @@ +// create_shared_object.hpp +// +// Written by Stephen Hewitt in 2025 +// GitHub repo: https://github.com/shewitt-au/std-enable_shared_from_this-and-constructors + +#pragma once +/* +The motivation for this code is issues with std::shared_ptr and +std::enable_shared_from_this. + +Consider code like this: + std::shared ptr = std::make_shared(); + +Assume that SomeClass's constructor uses shared_from_this. In this case, since +SomeClass is not yet owned by a std::shared_ptr, the shared_from_this call will +not work as expected. There seems to no way around this that I can find. +I wasn't aware of this issue. It was a real kick in the pants. + +The solution implemented here is two-stage construction. First the object is +constructed and assigned to a std::shared_ptr; then, if present, a +post_construct method is called with the same arguments. All code that uses +shared_from_this in the constructors should be moved to a post_construct method. +The intent of the "if present" is to enable incremental migration to two-stage +construction on demand. + +Another issue addressed is with std::make_shared. This function requires that +the constructor be public. If we're making factory methods for creation, we may +want to make the constructors non-public to stop misuse. The solution to this +problem I can't take credit for. + +The code for enable_shared_with_nonpublic_constructor is based on code found here +(called safe_enable_shared_from_this): + https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shared-on-a-class-with-only-protected-or-private-const +Posted by stackoverflow member Carsten. +He adapted old code from stackoverflow member Zsolt Rizsányi, +who in turn says it was invented by Jonathan Wakely (GCC developer). + +I have made minor modifications to suit and added comments. + +Requires C++23 +*/ + +#include +#include + +// Used to enable create_shared_object to access non-public constructors. +#define BEFRIEND_CREATE_SHARED_OBJECT(T) \ + friend struct shared_object_creator::enable_shared_with_nonpublic_constructor::Allocator; + +namespace shared_object_creator { + +// enable_shared_with_nonpublic_constructor was found here: +// https://stackoverflow.com/questions/8147027/how-do-i-call-stdmake-shared-on-a-class-with-only-protected-or-private-const +// +// Posted by stackoverflow member Carsten. +// He adapted old code from stackoverflow member Zsolt Rizsányi, +// who in turn says it was invented by Jonathan Wakely (GCC developer). +class enable_shared_with_nonpublic_constructor : public std::enable_shared_from_this { + // Our friends. They're not from around here and have long hard to pronounce names. + template + requires requires(T t, Args&&... args) { + t.post_construct(std::forward(args)...); + } + friend std::shared_ptr create_shared_object(Args&&... args); + + template + friend std::shared_ptr create_shared_object(Args&&... args); + +public: + virtual ~enable_shared_with_nonpublic_constructor() noexcept = default; + + // The next two functions use C++23's "explicit object parameter" + // syntax to make shared_from_this and weak_from_this, when called + // from derived classes, return a std::shared_ptr with T being + // the derived type. + template + auto inline shared_from_this(this TSelf&& self) noexcept + { + return std::static_pointer_cast>( + std::forward(self).std::template enable_shared_from_this::shared_from_this()); + } + + template + auto inline weak_from_this(this TSelf&& self) noexcept -> ::std::weak_ptr> + { + return std::static_pointer_cast>( + std::forward(self).std::template enable_shared_from_this::weak_from_this().lock()); + } + +protected: + enable_shared_with_nonpublic_constructor() noexcept = default; + enable_shared_with_nonpublic_constructor(enable_shared_with_nonpublic_constructor&&) noexcept = default; + enable_shared_with_nonpublic_constructor(const enable_shared_with_nonpublic_constructor&) noexcept = default; + enable_shared_with_nonpublic_constructor& operator=(enable_shared_with_nonpublic_constructor&&) noexcept = default; + enable_shared_with_nonpublic_constructor& operator=(const enable_shared_with_nonpublic_constructor&) noexcept = delete; + + template + struct Allocator : public std::allocator + { + template + void construct(TParent* parent, TArgs&&... args) + { ::new((void *)parent) TParent(std::forward(args)...); } + }; + +private: + // std::allocate_share, like std::make_shared, allocates both the object + // and the control block using only a single allocation. + template + static inline auto create(TArgs&&... args) -> std::shared_ptr { + return std::allocate_shared(Allocator{}, std::forward(args)...); + } +}; + +// The actual creation functions. + +template + requires requires(T t, Args&&... args) { + t.post_construct(std::forward(args)...); + } +std::shared_ptr create_shared_object(Args&&... args) { + auto p = enable_shared_with_nonpublic_constructor::create(std::forward(args)...); + p->post_construct(std::forward(args)...); + return p; +} + +template +std::shared_ptr create_shared_object(Args&&... args) { + return enable_shared_with_nonpublic_constructor::create(std::forward(args)...); +} + +} // namespace shared_object_creator diff --git a/lib/include/pl/patterns/pattern.hpp b/lib/include/pl/patterns/pattern.hpp index e0cd35da..6399d447 100644 --- a/lib/include/pl/patterns/pattern.hpp +++ b/lib/include/pl/patterns/pattern.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -14,6 +15,8 @@ #include #include +using namespace shared_object_creator; + namespace pl::ptrn { using namespace ::std::literals::string_literals; @@ -61,13 +64,14 @@ namespace pl::ptrn { friend class core::Evaluator; }; - class Pattern : public std::enable_shared_from_this { + class Pattern : public enable_shared_with_nonpublic_constructor { public: constexpr static u64 MainSectionId = 0x0000'0000'0000'0000; constexpr static u64 HeapSectionId = 0xFFFF'FFFF'FFFF'FFFF; constexpr static u64 PatternLocalSectionId = 0xFFFF'FFFF'FFFF'FFFE; constexpr static u64 InstantiationSectionId = 0xFFFF'FFFF'FFFF'FFFD; + protected: Pattern(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : m_evaluator(evaluator), m_line(line), m_offset(offset), m_size(size) { @@ -82,7 +86,7 @@ namespace pl::ptrn { } - Pattern(const Pattern &other) : std::enable_shared_from_this(other) { + Pattern(const Pattern &other) : enable_shared_with_nonpublic_constructor(other) { this->m_evaluator = other.m_evaluator; this->m_offset = other.m_offset; this->m_endian = other.m_endian; @@ -109,6 +113,7 @@ namespace pl::ptrn { } } + public: virtual ~Pattern() { if (this->m_evaluator != nullptr) { this->m_evaluator->patternDestroyed(this); @@ -116,6 +121,7 @@ namespace pl::ptrn { } virtual std::shared_ptr clone() const = 0; + std::shared_ptr reference() const { return shared_from_this(); } std::shared_ptr reference() { return shared_from_this(); } [[nodiscard]] u64 getOffset() const { return this->m_offset; } @@ -537,15 +543,15 @@ namespace pl::ptrn { this->m_initialized = initialized; } - [[nodiscard]] const Pattern* getParent() const { - return m_parent; + [[nodiscard]] const std::shared_ptr getParent() const { + return m_parent.lock(); } - [[nodiscard]] Pattern* getParent() { - return m_parent; + [[nodiscard]] std::shared_ptr getParent() { + return m_parent.lock(); } - void setParent(Pattern *parent) { + void setParent(std::shared_ptr parent) { m_parent = parent; } @@ -623,7 +629,7 @@ namespace pl::ptrn { core::Evaluator *m_evaluator; std::unique_ptr>> m_attributes; - Pattern *m_parent = nullptr; + std::weak_ptr m_parent; u32 m_line = 0; std::set::const_iterator m_variableName; @@ -641,6 +647,8 @@ namespace pl::ptrn { bool m_initialized = false; bool m_manualColor = false; + + BEFRIEND_CREATE_SHARED_OBJECT(Pattern) }; } diff --git a/lib/include/pl/patterns/pattern_array_dynamic.hpp b/lib/include/pl/patterns/pattern_array_dynamic.hpp index 7334f1eb..ef5f6abd 100644 --- a/lib/include/pl/patterns/pattern_array_dynamic.hpp +++ b/lib/include/pl/patterns/pattern_array_dynamic.hpp @@ -7,11 +7,14 @@ namespace pl::ptrn { class PatternArrayDynamic : public Pattern, public IInlinable, public IIndexable { - public: + protected: PatternArrayDynamic(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } - PatternArrayDynamic(const PatternArrayDynamic &other) : Pattern(other) { + PatternArrayDynamic(const PatternArrayDynamic &other) : Pattern(other) {} + + public: + void post_construct(const PatternArrayDynamic &other) { std::vector> entries; for (const auto &entry : other.m_entries) entries.push_back(entry->clone()); @@ -20,7 +23,7 @@ namespace pl::ptrn { } [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternArrayDynamic(*this)); + return create_shared_object(*this); } void setColor(u32 color) override { @@ -133,7 +136,7 @@ namespace pl::ptrn { if (!entry->hasOverriddenColor()) entry->setBaseColor(this->getColor()); - entry->setParent(this); + entry->setParent(this->reference()); this->m_entries.emplace_back(entry); } @@ -237,6 +240,8 @@ namespace pl::ptrn { private: std::vector> m_entries; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternArrayDynamic) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_array_static.hpp b/lib/include/pl/patterns/pattern_array_static.hpp index 36de9798..26e2b331 100644 --- a/lib/include/pl/patterns/pattern_array_static.hpp +++ b/lib/include/pl/patterns/pattern_array_static.hpp @@ -7,16 +7,19 @@ namespace pl::ptrn { class PatternArrayStatic : public Pattern, public IInlinable, public IIndexable { - public: + protected: PatternArrayStatic(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } - PatternArrayStatic(const PatternArrayStatic &other) : Pattern(other) { + PatternArrayStatic(const PatternArrayStatic &other) : Pattern(other) {} + + public: + void post_construct(const PatternArrayStatic &other) { this->setEntries(other.getTemplate()->clone(), other.getEntryCount()); } [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternArrayStatic(*this)); + return create_shared_object(*this); } [[nodiscard]] std::shared_ptr getEntry(size_t index) const override { @@ -153,7 +156,7 @@ namespace pl::ptrn { void setEntries(std::shared_ptr &&templatePattern, size_t count) { this->m_template = std::move(templatePattern); - this->m_template->setParent(this); + this->m_template->setParent(this->reference()); this->m_highlightTemplates.push_back(this->m_template->clone()); this->m_entryCount = count; @@ -252,6 +255,8 @@ namespace pl::ptrn { std::shared_ptr m_template = nullptr; mutable std::vector> m_highlightTemplates; size_t m_entryCount = 0; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternArrayStatic) }; } diff --git a/lib/include/pl/patterns/pattern_bitfield.hpp b/lib/include/pl/patterns/pattern_bitfield.hpp index de64a087..833cba07 100644 --- a/lib/include/pl/patterns/pattern_bitfield.hpp +++ b/lib/include/pl/patterns/pattern_bitfield.hpp @@ -6,13 +6,14 @@ namespace pl::ptrn { class PatternBitfieldMember : public Pattern { - public: + protected: using Pattern::Pattern; + public: [[nodiscard]] const PatternBitfieldMember& getTopmostBitfield() const { const PatternBitfieldMember* topBitfield = this; while (auto parent = topBitfield->getParent()) { - auto parentBitfield = dynamic_cast(parent); + auto parentBitfield = dynamic_cast(parent.get()); if (parentBitfield == nullptr) break; @@ -49,11 +50,13 @@ namespace pl::ptrn { std::vector getRawBytes() override { return { }; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldMember) }; class PatternBitfieldField : public PatternBitfieldMember { - public: - PatternBitfieldField(core::Evaluator *evaluator, u64 offset, u8 bitOffset, u8 bitSize, u32 line, PatternBitfieldMember *parentBitfield = nullptr) + protected: + PatternBitfieldField(core::Evaluator *evaluator, u64 offset, u8 bitOffset, u8 bitSize, u32 line, std::shared_ptr parentBitfield = nullptr) : PatternBitfieldMember(evaluator, offset, (bitOffset + bitSize + 7) / 8, line), m_bitOffset(bitOffset % 8), m_bitSize(bitSize) { this->setParent(parentBitfield); } @@ -64,8 +67,9 @@ namespace pl::ptrn { this->m_bitSize = other.m_bitSize; } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfieldField(*this)); + return create_shared_object(*this); } [[nodiscard]] u128 readValue() const { @@ -155,14 +159,17 @@ namespace pl::ptrn { u8 m_bitSize; bool m_padding = false; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldField) }; class PatternBitfieldFieldSigned : public PatternBitfieldField { - public: + protected: using PatternBitfieldField::PatternBitfieldField; + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfieldFieldSigned(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -179,14 +186,17 @@ namespace pl::ptrn { auto result = fmt::format("{}", this->getValue().toSigned()); return Pattern::callUserFormatFunc(this->getValue(), true).value_or(result); } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldFieldSigned) }; class PatternBitfieldFieldBoolean : public PatternBitfieldField { - public: + protected: using PatternBitfieldField::PatternBitfieldField; + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfieldFieldBoolean(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -211,12 +221,15 @@ namespace pl::ptrn { auto value = this->getValue(); return Pattern::callUserFormatFunc(value, true).value_or(fmt::format("{}", value.toBoolean() ? "true" : "false")); } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldFieldBoolean) }; class PatternBitfieldFieldEnum : public PatternBitfieldField { - public: + protected: using PatternBitfieldField::PatternBitfieldField; + public: [[nodiscard]] std::string getFormattedName() const override { return "enum " + Pattern::getTypeName(); } @@ -245,7 +258,7 @@ namespace pl::ptrn { } [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfieldFieldEnum(*this)); + return create_shared_object(*this); } std::string formatDisplayValue() override { @@ -261,12 +274,14 @@ namespace pl::ptrn { private: std::map m_enumValues; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldFieldEnum) }; class PatternBitfieldArray : public PatternBitfieldMember, public IInlinable, public IIndexable { - public: + protected: PatternBitfieldArray(core::Evaluator *evaluator, u64 offset, u8 firstBitOffset, u128 totalBitSize, u32 line) : PatternBitfieldMember(evaluator, offset, size_t((totalBitSize + 7) / 8), line), m_firstBitOffset(firstBitOffset), m_totalBitSize(totalBitSize) { } @@ -280,9 +295,10 @@ namespace pl::ptrn { this->m_firstBitOffset = other.m_firstBitOffset; this->m_totalBitSize = other.m_totalBitSize; } - + + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfieldArray(*this)); + return create_shared_object(*this); } [[nodiscard]] u8 getBitOffset() const override { @@ -422,7 +438,7 @@ namespace pl::ptrn { if (!entry->hasOverriddenColor()) entry->setBaseColor(this->getColor()); - entry->setParent(this); + entry->setParent(this->reference()); this->m_sortedEntries.push_back(entry.get()); } @@ -536,12 +552,14 @@ namespace pl::ptrn { u8 m_firstBitOffset = 0; u128 m_totalBitSize = 0; bool m_reversed = false; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfieldArray) }; - class PatternBitfield : public PatternBitfieldMember, - public IInlinable, - public IIterable { - public: +class PatternBitfield : public PatternBitfieldMember, + public IInlinable, + public IIterable { + protected: PatternBitfield(core::Evaluator *evaluator, u64 offset, u8 firstBitOffset, u128 totalBitSize, u32 line) : PatternBitfieldMember(evaluator, offset, size_t((totalBitSize + 7) / 8), line), m_firstBitOffset(firstBitOffset), m_totalBitSize(totalBitSize) { } @@ -553,8 +571,9 @@ namespace pl::ptrn { this->m_totalBitSize = other.m_totalBitSize; } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBitfield(*this)); + return create_shared_object(*this); } [[nodiscard]] u8 getBitOffset() const override { @@ -643,7 +662,7 @@ namespace pl::ptrn { this->setBaseColor(this->m_fields.front()->getColor()); for (const auto &field : this->m_fields) { - field->setParent(this); + field->setParent(this->reference()); this->m_sortedFields.push_back(field.get()); } } @@ -715,7 +734,7 @@ namespace pl::ptrn { } } else if (auto *member = dynamic_cast(pattern.get()); member != nullptr) { valueString += fmt::format("{} = {} | ", member->getVariableName(), member->toString()); - } else if (auto *bitfield = dynamic_cast(pattern.get()); bitfield != nullptr) { +} else if (auto *bitfield = dynamic_cast(pattern.get()); bitfield != nullptr) { valueString += fmt::format("{} = {} | ", bitfield->getVariableName(), bitfield->formatDisplayValue()); } } @@ -818,6 +837,8 @@ namespace pl::ptrn { u8 m_firstBitOffset = 0; u64 m_totalBitSize = 0; bool m_reversed = false; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBitfield) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_boolean.hpp b/lib/include/pl/patterns/pattern_boolean.hpp index af9bf441..0455ea2e 100644 --- a/lib/include/pl/patterns/pattern_boolean.hpp +++ b/lib/include/pl/patterns/pattern_boolean.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternBoolean : public Pattern { - public: + protected: explicit PatternBoolean(core::Evaluator *evaluator, u64 offset, u32 line) : Pattern(evaluator, offset, 1, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternBoolean(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -63,6 +64,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternBoolean) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_character.hpp b/lib/include/pl/patterns/pattern_character.hpp index 66578064..06c6da62 100644 --- a/lib/include/pl/patterns/pattern_character.hpp +++ b/lib/include/pl/patterns/pattern_character.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternCharacter : public Pattern { - public: + protected: PatternCharacter(core::Evaluator *evaluator, u64 offset, u32 line) : Pattern(evaluator, offset, 1, line) { } - + + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::make_unique(*this); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -59,6 +60,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternCharacter) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_enum.hpp b/lib/include/pl/patterns/pattern_enum.hpp index b5462397..2667be71 100644 --- a/lib/include/pl/patterns/pattern_enum.hpp +++ b/lib/include/pl/patterns/pattern_enum.hpp @@ -13,12 +13,13 @@ namespace pl::ptrn { [[nodiscard]] bool operator!=(const EnumValue &other) const = default; }; - public: + protected: PatternEnum(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternEnum(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -102,6 +103,8 @@ namespace pl::ptrn { private: std::map m_enumValues; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternEnum) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_error.hpp b/lib/include/pl/patterns/pattern_error.hpp index fc9e52be..3a169867 100644 --- a/lib/include/pl/patterns/pattern_error.hpp +++ b/lib/include/pl/patterns/pattern_error.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternError : public Pattern { - public: + protected: PatternError(core::Evaluator *evaluator, u64 offset, size_t size, u32 line, std::string errorMessage) : Pattern(evaluator, offset, size, line), m_errorMessage(std::move(errorMessage)) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternError(*this)); + return create_shared_object(*this); } [[nodiscard]] std::string getFormattedName() const override { @@ -41,6 +42,8 @@ namespace pl::ptrn { private: std::string m_errorMessage; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternError) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_float.hpp b/lib/include/pl/patterns/pattern_float.hpp index 96dbe4a9..7b79432e 100644 --- a/lib/include/pl/patterns/pattern_float.hpp +++ b/lib/include/pl/patterns/pattern_float.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternFloat : public Pattern { - public: + protected: PatternFloat(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternFloat(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -103,6 +104,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternFloat) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_padding.hpp b/lib/include/pl/patterns/pattern_padding.hpp index d3a95128..abc5539a 100644 --- a/lib/include/pl/patterns/pattern_padding.hpp +++ b/lib/include/pl/patterns/pattern_padding.hpp @@ -5,11 +5,12 @@ namespace pl::ptrn { class PatternPadding : public Pattern { - public: + protected: PatternPadding(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternPadding(*this)); + return create_shared_object(*this); } [[nodiscard]] std::string getFormattedName() const override { @@ -44,6 +45,8 @@ namespace pl::ptrn { std::vector getRawBytes() override { return { }; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternPadding) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_pointer.hpp b/lib/include/pl/patterns/pattern_pointer.hpp index 787d3c00..93d2237c 100644 --- a/lib/include/pl/patterns/pattern_pointer.hpp +++ b/lib/include/pl/patterns/pattern_pointer.hpp @@ -7,7 +7,7 @@ namespace pl::ptrn { class PatternPointer : public Pattern, public IInlinable { - public: + protected: PatternPointer(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line), m_pointedAt(nullptr), m_pointerType(nullptr) { } @@ -20,8 +20,9 @@ namespace pl::ptrn { } } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternPointer(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -180,6 +181,8 @@ namespace pl::ptrn { std::shared_ptr m_pointerType; i128 m_pointedAtAddress = 0; u64 m_pointerBase = 0; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternPointer) }; } diff --git a/lib/include/pl/patterns/pattern_signed.hpp b/lib/include/pl/patterns/pattern_signed.hpp index 94ad4b59..1dc4b687 100644 --- a/lib/include/pl/patterns/pattern_signed.hpp +++ b/lib/include/pl/patterns/pattern_signed.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternSigned : public Pattern { - public: + protected: PatternSigned(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternSigned(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -54,6 +55,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternSigned) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_string.hpp b/lib/include/pl/patterns/pattern_string.hpp index de726c9e..bd1febd3 100644 --- a/lib/include/pl/patterns/pattern_string.hpp +++ b/lib/include/pl/patterns/pattern_string.hpp @@ -8,12 +8,13 @@ namespace pl::ptrn { class PatternString : public Pattern, public IIndexable { - public: + protected: PatternString(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternString(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -76,7 +77,7 @@ namespace pl::ptrn { } std::shared_ptr getEntry(size_t index) const override { - auto result = std::make_shared(this->getEvaluator(), this->getOffset() + index, getLine()); + auto result = create_shared_object(this->getEvaluator(), this->getOffset() + index, getLine()); result->setSection(this->getSection()); return result; @@ -102,6 +103,7 @@ namespace pl::ptrn { return result; } + BEFRIEND_CREATE_SHARED_OBJECT(PatternString) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_struct.hpp b/lib/include/pl/patterns/pattern_struct.hpp index 3bd42bbd..3a4c7150 100644 --- a/lib/include/pl/patterns/pattern_struct.hpp +++ b/lib/include/pl/patterns/pattern_struct.hpp @@ -7,22 +7,25 @@ namespace pl::ptrn { class PatternStruct : public Pattern, public IInlinable, public IIterable { - public: + protected: PatternStruct(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } - PatternStruct(const PatternStruct &other) : Pattern(other) { + PatternStruct(const PatternStruct &other) : Pattern(other) {} + + public: + void post_construct(const PatternStruct &other) { for (const auto &member : other.m_members) { auto copy = member->clone(); - copy->setParent(this); + copy->setParent(this->reference()); this->m_sortedMembers.push_back(copy.get()); this->m_members.push_back(std::move(copy)); } } [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternStruct(*this)); + return create_shared_object(*this); } [[nodiscard]] std::shared_ptr getEntry(size_t index) const override { @@ -36,7 +39,7 @@ namespace pl::ptrn { void addEntry(const std::shared_ptr &entry) override { if (entry == nullptr) return; - entry->setParent(this); + entry->setParent(this->reference()); this->m_sortedMembers.push_back(entry.get()); this->m_members.push_back(entry); } @@ -229,6 +232,8 @@ namespace pl::ptrn { private: std::vector> m_members; std::vector m_sortedMembers; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternStruct) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_union.hpp b/lib/include/pl/patterns/pattern_union.hpp index fa2939e3..c7f1d510 100644 --- a/lib/include/pl/patterns/pattern_union.hpp +++ b/lib/include/pl/patterns/pattern_union.hpp @@ -7,7 +7,7 @@ namespace pl::ptrn { class PatternUnion : public Pattern, public IInlinable, public IIterable { - public: + protected: PatternUnion(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } @@ -20,8 +20,9 @@ namespace pl::ptrn { } } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternUnion(*this)); + return create_shared_object(*this); } [[nodiscard]] std::shared_ptr getEntry(size_t index) const override { @@ -35,7 +36,7 @@ namespace pl::ptrn { void addEntry(const std::shared_ptr &entry) override { if (entry == nullptr) return; - entry->setParent(this); + entry->setParent(this->reference()); this->m_sortedMembers.push_back(entry.get()); this->m_members.push_back(entry); } @@ -221,6 +222,8 @@ namespace pl::ptrn { private: std::vector> m_members; std::vector m_sortedMembers; + + BEFRIEND_CREATE_SHARED_OBJECT(PatternUnion) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_unsigned.hpp b/lib/include/pl/patterns/pattern_unsigned.hpp index 6cb650de..7dee412b 100644 --- a/lib/include/pl/patterns/pattern_unsigned.hpp +++ b/lib/include/pl/patterns/pattern_unsigned.hpp @@ -5,12 +5,13 @@ namespace pl::ptrn { class PatternUnsigned : public Pattern { - public: + protected: PatternUnsigned(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternUnsigned(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -51,6 +52,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternUnsigned) }; } \ No newline at end of file diff --git a/lib/include/pl/patterns/pattern_wide_character.hpp b/lib/include/pl/patterns/pattern_wide_character.hpp index 1bc28b7c..ac6d1f64 100644 --- a/lib/include/pl/patterns/pattern_wide_character.hpp +++ b/lib/include/pl/patterns/pattern_wide_character.hpp @@ -7,12 +7,13 @@ namespace pl::ptrn { class PatternWideCharacter : public Pattern { - public: + protected: explicit PatternWideCharacter(core::Evaluator *evaluator, u64 offset, u32 line) : Pattern(evaluator, offset, 2, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternWideCharacter(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -55,6 +56,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternWideCharacter) }; } diff --git a/lib/include/pl/patterns/pattern_wide_string.hpp b/lib/include/pl/patterns/pattern_wide_string.hpp index 5b033492..264fa47b 100644 --- a/lib/include/pl/patterns/pattern_wide_string.hpp +++ b/lib/include/pl/patterns/pattern_wide_string.hpp @@ -8,12 +8,13 @@ namespace pl::ptrn { class PatternWideString : public Pattern, public IIndexable { - public: + protected: PatternWideString(core::Evaluator *evaluator, u64 offset, size_t size, u32 line) : Pattern(evaluator, offset, size, line) { } + public: [[nodiscard]] std::shared_ptr clone() const override { - return std::unique_ptr(new PatternWideString(*this)); + return create_shared_object(*this); } [[nodiscard]] core::Token::Literal getValue() const override { @@ -80,7 +81,7 @@ namespace pl::ptrn { } std::shared_ptr getEntry(size_t index) const override { - auto result = std::make_shared(this->getEvaluator(), this->getOffset() + index * sizeof(char16_t), getLine()); + auto result = create_shared_object(this->getEvaluator(), this->getOffset() + index * sizeof(char16_t), getLine()); result->setSection(this->getSection()); return result; @@ -105,6 +106,8 @@ namespace pl::ptrn { return result; } + + BEFRIEND_CREATE_SHARED_OBJECT(PatternWideString) }; } diff --git a/lib/source/pl/core/ast/ast_node_array_variable_decl.cpp b/lib/source/pl/core/ast/ast_node_array_variable_decl.cpp index b10309de..bcb5ab5a 100644 --- a/lib/source/pl/core/ast/ast_node_array_variable_decl.cpp +++ b/lib/source/pl/core/ast/ast_node_array_variable_decl.cpp @@ -217,14 +217,14 @@ namespace pl::core::ast { } } - if (dynamic_cast(templatePattern.get())) { - outputPattern = std::make_unique(evaluator, startOffset, 0, getLocation().line); - } else if (dynamic_cast(templatePattern.get())) { - outputPattern = std::make_unique(evaluator, startOffset, 0, getLocation().line); - } else if (dynamic_cast(templatePattern.get())) { - outputPattern = std::make_unique(evaluator, startOffset, 0, getLocation().line); + if (std::dynamic_pointer_cast(templatePattern)) { + outputPattern = create_shared_object(evaluator, startOffset, 0, getLocation().line); + } else if (std::dynamic_pointer_cast(templatePattern)) { + outputPattern = create_shared_object(evaluator, startOffset, 0, getLocation().line); + } else if (std::dynamic_pointer_cast(templatePattern)) { + outputPattern = create_shared_object(evaluator, startOffset, 0, getLocation().line); } else { - auto arrayPattern = std::make_unique(evaluator, startOffset, 0, getLocation().line); + auto arrayPattern = create_shared_object(evaluator, startOffset, 0, getLocation().line); arrayPattern->setEntries(templatePattern->clone(), size_t(entryCount)); arrayPattern->setSection(templatePattern->getSection()); outputPattern = std::move(arrayPattern); @@ -256,7 +256,7 @@ namespace pl::core::ast { }; evaluator->alignToByte(); - auto arrayPattern = std::make_unique(evaluator, evaluator->getReadOffset(), 0, getLocation().line); + auto arrayPattern = create_shared_object(evaluator, evaluator->getReadOffset(), 0, getLocation().line); arrayPattern->setVariableName(this->m_name); arrayPattern->setSection(evaluator->getSectionId()); diff --git a/lib/source/pl/core/ast/ast_node_bitfield.cpp b/lib/source/pl/core/ast/ast_node_bitfield.cpp index fde1deca..47f13558 100644 --- a/lib/source/pl/core/ast/ast_node_bitfield.cpp +++ b/lib/source/pl/core/ast/ast_node_bitfield.cpp @@ -26,7 +26,7 @@ namespace pl::core::ast { [[maybe_unused]] auto context = evaluator->updateRuntime(this); auto position = evaluator->getBitwiseReadOffset(); - auto bitfieldPattern = std::make_shared(evaluator, position.byteOffset, position.bitOffset, 0, getLocation().line); + auto bitfieldPattern = create_shared_object(evaluator, position.byteOffset, position.bitOffset, 0, getLocation().line); bitfieldPattern->setSection(evaluator->getSectionId()); @@ -138,8 +138,8 @@ namespace pl::core::ast { } for (auto &pattern : potentialPatterns) { - if (auto bitfieldMember = dynamic_cast(pattern.get()); bitfieldMember != nullptr) { - bitfieldMember->setParent(bitfieldPattern.get()); + if (auto bitfieldMember = std::dynamic_pointer_cast(pattern); bitfieldMember != nullptr) { + bitfieldMember->setParent(bitfieldPattern); if (!bitfieldMember->isPadding()) fields.push_back(pattern); } else { diff --git a/lib/source/pl/core/ast/ast_node_bitfield_array_variable_decl.cpp b/lib/source/pl/core/ast/ast_node_bitfield_array_variable_decl.cpp index 7a87c518..c31b68c3 100644 --- a/lib/source/pl/core/ast/ast_node_bitfield_array_variable_decl.cpp +++ b/lib/source/pl/core/ast/ast_node_bitfield_array_variable_decl.cpp @@ -53,7 +53,7 @@ namespace pl::core::ast { }; auto position = evaluator->getBitwiseReadOffset(); - auto arrayPattern = std::make_unique(evaluator, position.byteOffset, position.bitOffset, 0, getLocation().line); + auto arrayPattern = create_shared_object(evaluator, position.byteOffset, position.bitOffset, 0, getLocation().line); arrayPattern->setVariableName(this->m_name); arrayPattern->setSection(evaluator->getSectionId()); arrayPattern->setReversed(evaluator->isReadOrderReversed()); @@ -132,8 +132,8 @@ namespace pl::core::ast { } for (auto &pattern : entries) { - if (auto bitfieldMember = dynamic_cast(pattern.get()); bitfieldMember != nullptr) - bitfieldMember->setParent(arrayPattern.get()); + if (auto bitfieldMember = std::dynamic_pointer_cast(pattern); bitfieldMember != nullptr) + bitfieldMember->setParent(arrayPattern); } arrayPattern->setEntries(entries); diff --git a/lib/source/pl/core/ast/ast_node_bitfield_field.cpp b/lib/source/pl/core/ast/ast_node_bitfield_field.cpp index e887bfec..0719d277 100644 --- a/lib/source/pl/core/ast/ast_node_bitfield_field.cpp +++ b/lib/source/pl/core/ast/ast_node_bitfield_field.cpp @@ -25,7 +25,7 @@ namespace pl::core::ast { [[nodiscard]] bool ASTNodeBitfieldField::isPadding() const { return this->getName() == "$padding$"; } [[nodiscard]] std::shared_ptr ASTNodeBitfieldField::createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const { - return std::make_shared(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); + return create_shared_object(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); } void ASTNodeBitfieldField::createPatterns(Evaluator *evaluator, std::vector> &resultPatterns) const { @@ -57,7 +57,7 @@ namespace pl::core::ast { [[nodiscard]] std::shared_ptr ASTNodeBitfieldFieldSigned::createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const { - return std::make_shared(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); + return create_shared_object(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); } @@ -68,29 +68,28 @@ namespace pl::core::ast { this->m_type = std::unique_ptr(static_cast(other.m_type->clone().release())); } -[[nodiscard]] std::shared_ptr ASTNodeBitfieldFieldSizedType::createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const { - auto originalPosition = evaluator->getBitwiseReadOffset(); - evaluator->setBitwiseReadOffset(byteOffset, bitOffset); - - std::vector> patterns; - this->m_type->createPatterns(evaluator, patterns); - auto &pattern = patterns[0]; - std::shared_ptr result = nullptr; - evaluator->setBitwiseReadOffset(originalPosition); - - if (auto *patternEnum = dynamic_cast(pattern.get()); patternEnum != nullptr) { - auto bitfieldEnum = std::make_unique(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); - bitfieldEnum->setTypeName(patternEnum->getTypeName()); - bitfieldEnum->setEnumValues(patternEnum->getEnumValues()); - result = std::move(bitfieldEnum); - } else if (dynamic_cast(pattern.get()) != nullptr) { - result = std::make_shared(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); - } else { - err::E0004.throwError("Bit size specifiers may only be used with unsigned, signed, bool or enum types.", {}, this->getLocation()); + [[nodiscard]] std::shared_ptr ASTNodeBitfieldFieldSizedType::createBitfield(Evaluator *evaluator, u64 byteOffset, u8 bitOffset, u8 bitSize) const { + auto originalPosition = evaluator->getBitwiseReadOffset(); + evaluator->setBitwiseReadOffset(byteOffset, bitOffset); + + std::vector> patterns; + this->m_type->createPatterns(evaluator, patterns); + auto &pattern = patterns[0]; + std::shared_ptr result = nullptr; + evaluator->setBitwiseReadOffset(originalPosition); + + if (auto *patternEnum = dynamic_cast(pattern.get()); patternEnum != nullptr) { + auto bitfieldEnum = create_shared_object(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); + bitfieldEnum->setTypeName(patternEnum->getTypeName()); + bitfieldEnum->setEnumValues(patternEnum->getEnumValues()); + result = std::move(bitfieldEnum); + } else if (dynamic_cast(pattern.get()) != nullptr) { + result = create_shared_object(evaluator, byteOffset, bitOffset, bitSize, getLocation().line); + } else { + err::E0004.throwError("Bit size specifiers may only be used with unsigned, signed, bool or enum types.", {}, this->getLocation()); + } + + return result; } - return result; -} - - } \ No newline at end of file diff --git a/lib/source/pl/core/ast/ast_node_builtin_type.cpp b/lib/source/pl/core/ast/ast_node_builtin_type.cpp index 9f0b2a29..45dc80c6 100644 --- a/lib/source/pl/core/ast/ast_node_builtin_type.cpp +++ b/lib/source/pl/core/ast/ast_node_builtin_type.cpp @@ -23,23 +23,23 @@ namespace pl::core::ast { auto size = Token::getTypeSize(this->m_type); auto offset = evaluator->getReadOffsetAndIncrement(size); - std::unique_ptr pattern; + std::shared_ptr pattern; if (Token::isUnsigned(this->m_type)) - pattern = std::make_unique(evaluator, offset, size, getLocation().line); + pattern = create_shared_object(evaluator, offset, size, getLocation().line); else if (Token::isSigned(this->m_type)) - pattern = std::make_unique(evaluator, offset, size, getLocation().line); + pattern = create_shared_object(evaluator, offset, size, getLocation().line); else if (Token::isFloatingPoint(this->m_type)) - pattern = std::make_unique(evaluator, offset, size, getLocation().line); + pattern = create_shared_object(evaluator, offset, size, getLocation().line); else if (this->m_type == Token::ValueType::Boolean) - pattern = std::make_unique(evaluator, offset, getLocation().line); + pattern = create_shared_object(evaluator, offset, getLocation().line); else if (this->m_type == Token::ValueType::Character) - pattern = std::make_unique(evaluator, offset, getLocation().line); + pattern = create_shared_object(evaluator, offset, getLocation().line); else if (this->m_type == Token::ValueType::Character16) - pattern = std::make_unique(evaluator, offset, getLocation().line); + pattern = create_shared_object(evaluator, offset, getLocation().line); else if (this->m_type == Token::ValueType::Padding) - pattern = std::make_unique(evaluator, offset, 1, getLocation().line); + pattern = create_shared_object(evaluator, offset, 1, getLocation().line); else if (this->m_type == Token::ValueType::String) - pattern = std::make_unique(evaluator, offset, 0, getLocation().line); + pattern = create_shared_object(evaluator, offset, 0, getLocation().line); else if (this->m_type == Token::ValueType::CustomType) { std::vector params; diff --git a/lib/source/pl/core/ast/ast_node_enum.cpp b/lib/source/pl/core/ast/ast_node_enum.cpp index d54dc5ab..f97a3d0a 100644 --- a/lib/source/pl/core/ast/ast_node_enum.cpp +++ b/lib/source/pl/core/ast/ast_node_enum.cpp @@ -73,7 +73,7 @@ namespace pl::core::ast { err::E0005.throwError("'auto' can only be used with parameters.", { }, this->getLocation()); auto &underlying = underlyingTypePatterns.front(); - auto pattern = std::make_shared(evaluator, underlying->getOffset(), 0, getLocation().line); + auto pattern = create_shared_object(evaluator, underlying->getOffset(), 0, getLocation().line); pattern->setSection(evaluator->getSectionId()); diff --git a/lib/source/pl/core/ast/ast_node_imported_type.cpp b/lib/source/pl/core/ast/ast_node_imported_type.cpp index 6f2858de..8884d149 100644 --- a/lib/source/pl/core/ast/ast_node_imported_type.cpp +++ b/lib/source/pl/core/ast/ast_node_imported_type.cpp @@ -33,7 +33,7 @@ namespace pl::core::ast { result = std::move(pattern); } else { - auto structPattern = std::make_shared(evaluator, 0x00, 0, getLocation().line); + auto structPattern = create_shared_object(evaluator, 0x00, 0, getLocation().line); u64 minPos = std::numeric_limits::max(); u64 maxPos = std::numeric_limits::min(); diff --git a/lib/source/pl/core/ast/ast_node_pointer_variable_decl.cpp b/lib/source/pl/core/ast/ast_node_pointer_variable_decl.cpp index 427625b6..b7d535a7 100644 --- a/lib/source/pl/core/ast/ast_node_pointer_variable_decl.cpp +++ b/lib/source/pl/core/ast/ast_node_pointer_variable_decl.cpp @@ -67,7 +67,7 @@ namespace pl::core::ast { auto &sizePattern = sizePatterns.front(); sizePattern->setSection(evaluator->getSectionId()); - auto pattern = std::make_shared(evaluator, pointerStartOffset, sizePattern->getSize(), getLocation().line); + auto pattern = create_shared_object(evaluator, pointerStartOffset, sizePattern->getSize(), getLocation().line); pattern->setVariableName(this->m_name); pattern->setPointerTypePattern(std::move(sizePattern)); diff --git a/lib/source/pl/core/ast/ast_node_rvalue.cpp b/lib/source/pl/core/ast/ast_node_rvalue.cpp index d3eb73d3..cb9910ba 100644 --- a/lib/source/pl/core/ast/ast_node_rvalue.cpp +++ b/lib/source/pl/core/ast/ast_node_rvalue.cpp @@ -56,7 +56,7 @@ namespace pl::core::ast { if (auto name = std::get_if(&this->getPath().front()); name != nullptr) { if (*name == "$") return std::make_unique(u128(evaluator->getReadOffset())); else if (*name == "null") return std::make_unique( - std::make_shared(evaluator, 0, 0, getLocation().line)); + create_shared_object(evaluator, 0, 0, getLocation().line)); // Why? auto parameterPack = evaluator->getScope(0).parameterPack; if (parameterPack && *name == parameterPack->name) diff --git a/lib/source/pl/core/ast/ast_node_struct.cpp b/lib/source/pl/core/ast/ast_node_struct.cpp index e1cdec3c..25891499 100644 --- a/lib/source/pl/core/ast/ast_node_struct.cpp +++ b/lib/source/pl/core/ast/ast_node_struct.cpp @@ -18,7 +18,7 @@ namespace pl::core::ast { [[maybe_unused]] auto context = evaluator->updateRuntime(this); evaluator->alignToByte(); - auto pattern = std::make_shared(evaluator, evaluator->getReadOffset(), 0, getLocation().line); + auto pattern = create_shared_object(evaluator, evaluator->getReadOffset(), 0, getLocation().line); auto startOffset = evaluator->getReadOffset(); std::vector> memberPatterns; diff --git a/lib/source/pl/core/ast/ast_node_union.cpp b/lib/source/pl/core/ast/ast_node_union.cpp index b18bddbe..113afddd 100644 --- a/lib/source/pl/core/ast/ast_node_union.cpp +++ b/lib/source/pl/core/ast/ast_node_union.cpp @@ -16,7 +16,7 @@ namespace pl::core::ast { [[maybe_unused]] auto context = evaluator->updateRuntime(this); evaluator->alignToByte(); - auto pattern = std::make_shared(evaluator, evaluator->getReadOffset(), 0, getLocation().line); + auto pattern = create_shared_object(evaluator, evaluator->getReadOffset(), 0, getLocation().line); std::vector> memberPatterns; u64 startOffset = evaluator->getReadOffset(); diff --git a/lib/source/pl/core/evaluator.cpp b/lib/source/pl/core/evaluator.cpp index 4467c362..fc5c6e68 100644 --- a/lib/source/pl/core/evaluator.cpp +++ b/lib/source/pl/core/evaluator.cpp @@ -225,7 +225,7 @@ namespace pl::core { this->setBitwiseReadOffset(startOffset); - auto pattern = new ptrn::PatternArrayDynamic(this, 0, typePattern->getSize() * entryCount, 0); + auto pattern = create_shared_object(this, 0, typePattern->getSize() * entryCount, 0); if (section == ptrn::Pattern::PatternLocalSectionId) { typePattern->setSection(section); @@ -277,7 +277,7 @@ namespace pl::core { this->getConsole().log(LogConsole::Level::Debug, fmt::format("Creating local array variable '{} {}[{}]' at heap address 0x{:X}.", pattern->getTypeName(), pattern->getVariableName(), entryCount, pattern->getOffset())); pattern->setConstant(constant); - variables.push_back(std::unique_ptr(pattern)); + variables.push_back(pattern); } std::optional Evaluator::findTypeName(const ast::ASTNodeTypeDecl *type) { @@ -396,19 +396,19 @@ namespace pl::core { if (auto builtinType = getBuiltinType(type); builtinType != nullptr && builtinType->getType() == Token::ValueType::Auto) { // Handle auto variables if (!value.has_value()) - pattern = std::make_shared(this, 0, 0, 0); + pattern = create_shared_object(this, 0, 0, 0); else if (std::get_if(&value.value()) != nullptr) - pattern = std::make_shared(this, 0, sizeof(u128), 0); + pattern = create_shared_object(this, 0, sizeof(u128), 0); else if (std::get_if(&value.value()) != nullptr) - pattern = std::make_shared(this, 0, sizeof(i128), 0); + pattern = create_shared_object(this, 0, sizeof(i128), 0); else if (std::get_if(&value.value()) != nullptr) - pattern = std::make_shared(this, 0, sizeof(double), 0); + pattern = create_shared_object(this, 0, sizeof(double), 0); else if (std::get_if(&value.value()) != nullptr) - pattern = std::make_shared(this, 0, 0); + pattern = create_shared_object(this, 0, 0); else if (std::get_if(&value.value()) != nullptr) - pattern = std::make_shared(this, 0, 0); + pattern = create_shared_object(this, 0, 0); else if (auto string = std::get_if(&value.value()); string != nullptr) - pattern = std::make_shared(this, 0, string->size(), 0); + pattern = create_shared_object(this, 0, string->size(), 0); else if (auto patternValue = std::get_if>(&value.value()); patternValue != nullptr) { if (reference && !templateVariable) pattern = *patternValue; @@ -424,7 +424,7 @@ namespace pl::core { pattern = std::move(patterns.front()); } else { - pattern = std::make_shared(this, 0, 0, 0); + pattern = create_shared_object(this, 0, 0, 0); if (auto typeName = findTypeName(type); typeName.has_value()) pattern->setTypeName(typeName.value()); @@ -725,32 +725,32 @@ namespace pl::core { std::visit(wolv::util::overloaded { [&](const u128 &value) { - changePatternType(pattern, std::make_shared(this, 0, 16, 0)); + changePatternType(pattern, create_shared_object(this, 0, 16, 0)); auto adjustedValue = hlp::changeEndianess(value, pattern->getSize(), pattern->getEndian()); copyToStorage(adjustedValue); }, [&](const i128 &value) { - changePatternType(pattern, std::make_shared(this, 0, 16, 0)); + changePatternType(pattern, create_shared_object(this, 0, 16, 0)); auto adjustedValue = hlp::changeEndianess(value, pattern->getSize(), pattern->getEndian()); adjustedValue = hlp::signExtend(pattern->getSize() * 8, adjustedValue); copyToStorage(adjustedValue); }, [&](const bool &value) { - changePatternType(pattern, std::make_shared(this, 0, 0)); + changePatternType(pattern, create_shared_object(this, 0, 0)); auto adjustedValue = hlp::changeEndianess(value, pattern->getSize(), pattern->getEndian()); copyToStorage(adjustedValue); }, [&](const char &value) { - changePatternType(pattern, std::make_shared(this, 0, 0)); + changePatternType(pattern, create_shared_object(this, 0, 0)); auto adjustedValue = hlp::changeEndianess(value, pattern->getSize(), pattern->getEndian()); copyToStorage(adjustedValue); }, [&](const double &value) { - changePatternType(pattern, std::make_shared(this, 0, 8, 0)); + changePatternType(pattern, create_shared_object(this, 0, 8, 0)); if (pattern->getSize() == sizeof(float)) { auto floatValue = float(value); @@ -768,7 +768,7 @@ namespace pl::core { } }, [&](const std::string &value) { - changePatternType(pattern, std::make_shared(this, 0, value.length(), 0)); + changePatternType(pattern, create_shared_object(this, 0, value.length(), 0)); pattern->setSize(value.size()); diff --git a/lib/source/pl/pattern_language.cpp b/lib/source/pl/pattern_language.cpp index 945cf7b1..0c6dbccd 100644 --- a/lib/source/pl/pattern_language.cpp +++ b/lib/source/pl/pattern_language.cpp @@ -552,7 +552,7 @@ namespace pl { ptrn::Pattern* value = interval.value; auto parent = value->getParent(); - while (parent != nullptr && dynamic_cast(parent->getParent()) == nullptr) { + while (parent != nullptr && std::dynamic_pointer_cast(parent->getParent()) == nullptr) { parent = parent->getParent(); } diff --git a/tests/include/test_patterns/test_pattern.hpp b/tests/include/test_patterns/test_pattern.hpp index 78a054b0..bfa77743 100644 --- a/tests/include/test_patterns/test_pattern.hpp +++ b/tests/include/test_patterns/test_pattern.hpp @@ -30,8 +30,8 @@ namespace pl::test { virtual ~TestPattern() = default; template - std::unique_ptr create(const std::string &typeName, const std::string &varName, auto... args) { - auto pattern = std::make_unique(m_evaluator, args...); + std::shared_ptr create(const std::string &typeName, const std::string &varName, auto... args) { + auto pattern = create_shared_object(m_evaluator, args...); pattern->setTypeName(typeName); pattern->setVariableName(varName); @@ -40,8 +40,8 @@ namespace pl::test { [[nodiscard]] virtual std::string getSourceCode() const = 0; - [[nodiscard]] virtual const std::vector> &getPatterns() const final { return this->m_patterns; } - virtual void addPattern(std::unique_ptr &&pattern) final { + [[nodiscard]] virtual const std::vector> &getPatterns() const final { return this->m_patterns; } + virtual void addPattern(std::shared_ptr &&pattern) final { this->m_patterns.push_back(std::move(pattern)); } @@ -60,7 +60,7 @@ namespace pl::test { } private: - std::vector> m_patterns; + std::vector> m_patterns; core::Evaluator *m_evaluator; Mode m_mode; diff --git a/tests/include/test_patterns/test_pattern_bitfields.hpp b/tests/include/test_patterns/test_pattern_bitfields.hpp index 0b41af6d..abf84c1b 100644 --- a/tests/include/test_patterns/test_pattern_bitfields.hpp +++ b/tests/include/test_patterns/test_pattern_bitfields.hpp @@ -6,6 +6,12 @@ namespace pl::test { + template + std::shared_ptr downcast_ref(std::shared_ptr pat) + { + return std::dynamic_pointer_cast(pat->reference()); + } + class TestPatternBitfields : public TestPattern { public: TestPatternBitfields(core::Evaluator *evaluator) : TestPattern(evaluator, "Bitfields") { @@ -13,22 +19,22 @@ namespace pl::test { std::vector> bitfieldFields; { - bitfieldFields.push_back(create("", "a", 0x25, 0, 2, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "b", 0x25, 2, 3, 0, testBitfield.get())); + bitfieldFields.push_back(create("", "a", 0x25, 0, 2, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "b", 0x25, 2, 3, 0, downcast_ref(testBitfield))); auto nestedBitfield = create("NestedBitfield", "c", 0x25, 5, 4 * 2, 0); std::vector> nestedFields; { - nestedFields.push_back(create("", "nestedA", 0x25, 5, 4, 0, testBitfield.get())); - nestedFields.push_back(create("", "nestedB", 0x26, 1, 4, 0, testBitfield.get())); + nestedFields.push_back(create("", "nestedA", 0x25, 5, 4, 0, downcast_ref(testBitfield))); + nestedFields.push_back(create("", "nestedB", 0x26, 1, 4, 0, downcast_ref(testBitfield))); } - nestedBitfield->setParent(testBitfield.get()); + nestedBitfield->setParent(downcast_ref(testBitfield)); nestedBitfield->setFields(std::move(nestedFields)); nestedBitfield->setEndian(std::endian::big); bitfieldFields.push_back(std::move(nestedBitfield)); - bitfieldFields.push_back(create("", "d", 0x26, 5, 4, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "e", 0x27, 1, 4, 0, testBitfield.get())); + bitfieldFields.push_back(create("", "d", 0x26, 5, 4, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "e", 0x27, 1, 4, 0, downcast_ref(testBitfield))); auto array = create("NestedBitfield", "f", 0x27, 5, 4 * 4, 0); std::vector> arrayEntries; @@ -36,10 +42,10 @@ namespace pl::test { auto array0Bitfield = create("NestedBitfield", "[0]", 0x27, 5, 4 * 2, 0); std::vector> array0Fields; { - array0Fields.push_back(create("", "nestedA", 0x27, 5, 4, 0, array0Bitfield.get())); - array0Fields.push_back(create("", "nestedB", 0x28, 1, 4, 0, array0Bitfield.get())); + array0Fields.push_back(create("", "nestedA", 0x27, 5, 4, 0, downcast_ref(array0Bitfield))); + array0Fields.push_back(create("", "nestedB", 0x28, 1, 4, 0, downcast_ref(array0Bitfield))); } - array0Bitfield->setParent(array.get()); + array0Bitfield->setParent(array->reference()); array0Bitfield->setFields(std::move(array0Fields)); array0Bitfield->setEndian(std::endian::big); arrayEntries.push_back(std::move(array0Bitfield)); @@ -47,15 +53,15 @@ namespace pl::test { auto array1Bitfield = create("NestedBitfield", "[1]", 0x28, 5, 4 * 2, 0); std::vector> array1Fields; { - array1Fields.push_back(create("", "nestedA", 0x28, 5, 4, 0, array1Bitfield.get())); - array1Fields.push_back(create("", "nestedB", 0x29, 1, 4, 0, array1Bitfield.get())); + array1Fields.push_back(create("", "nestedA", 0x28, 5, 4, 0, downcast_ref(array1Bitfield))); + array1Fields.push_back(create("", "nestedB", 0x29, 1, 4, 0, downcast_ref(array1Bitfield))); } - array1Bitfield->setParent(array.get()); + array1Bitfield->setParent(array->reference()); array1Bitfield->setFields(std::move(array1Fields)); array1Bitfield->setEndian(std::endian::big); arrayEntries.push_back(std::move(array1Bitfield)); } - array->setParent(testBitfield.get()); + array->setParent(downcast_ref(testBitfield)); array->setEntries(arrayEntries); array->setEndian(std::endian::big); bitfieldFields.push_back(std::move(array)); @@ -107,14 +113,14 @@ namespace pl::test { std::vector> bitfieldFields; { - bitfieldFields.push_back(create("", "flag0", 0x03, 7, 1, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "flag1", 0x03, 6, 1, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "flag2", 0x03, 5, 1, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "flag3", 0x03, 4, 1, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "flag4", 0x03, 3, 1, 0, testBitfield.get())); - bitfieldFields.push_back(create("", "flag5", 0x03, 2, 1, 0, testBitfield.get())); - - auto enumField = create("Enum", "enumerated", 0x02, 4, 6, 0, testBitfield.get()); + bitfieldFields.push_back(create("", "flag0", 0x03, 7, 1, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "flag1", 0x03, 6, 1, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "flag2", 0x03, 5, 1, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "flag3", 0x03, 4, 1, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "flag4", 0x03, 3, 1, 0, downcast_ref(testBitfield))); + bitfieldFields.push_back(create("", "flag5", 0x03, 2, 1, 0, downcast_ref(testBitfield))); + + auto enumField = create("Enum", "enumerated", 0x02, 4, 6, 0, downcast_ref(testBitfield)); std::map values; { values.insert({ "A", { 0x39, 0x39 } });