From 61162deea76d9e32bde00b6f5d0a399cc6997413 Mon Sep 17 00:00:00 2001 From: r0qs Date: Mon, 28 Aug 2023 13:46:25 +0200 Subject: [PATCH] Fix subObjectAt --- libyul/Object.cpp | 29 ++++++++++++++++++++++------- libyul/Object.h | 11 ++++------- test/tools/yulopti.cpp | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 0ea9009fb..e871b70db 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -164,10 +164,12 @@ void Object::visitPath(YulString _qualifiedName, std::functionsubObjects.end()) { object = dynamic_cast(subObjectIt->get()); - yulAssert(object, "Assembly object <" + object->name.str() + "> not found or does not contain code."); - yulAssert(object->subId != std::numeric_limits::max(), ""); - if (_visitor(object)) - break; + if (object) + { + yulAssert(object, "Assembly object <" + object->name.str() + "> not found or does not contain code."); + if (_visitor(object)) + break; + } } } } @@ -183,17 +185,30 @@ std::vector Object::pathToSubObject(YulString _qualifiedName) const yulAssert(!_qualifiedName.empty(), ""); this->visitPath(_qualifiedName, [&](Object const* _object) -> bool { + yulAssert(_object->subId != std::numeric_limits::max(), ""); path.push_back({_object->subId}); return false; }); return path; } -std::shared_ptr Object::objectAt(std::shared_ptr const& _object, std::string const& _qualifiedName) +std::shared_ptr Object::subObjectAt(std::string const& _qualifiedName) { + + if (_qualifiedName.empty()) + return nullptr; + + // If there is no `.` in the given `_qualifiedName`, the target + // object name is considered to be the `_qualifiedName`, otherwise, + // the target object name is the last element in the path given by `_qualifiedName`. + std::string targetObjectName = _qualifiedName; + size_t targetObjectPos = _qualifiedName.find_last_of("."); + if (targetObjectPos != std::string::npos) + targetObjectName = _qualifiedName.substr(targetObjectPos + 1); + std::shared_ptr foundObject = nullptr; - _object->visitPath(YulString(_qualifiedName), [&](Object const* _subObject) -> bool { - if (_qualifiedName.empty() || _qualifiedName == _subObject->name.str()) + this->visitPath(YulString(_qualifiedName), [&](Object const* _subObject) -> bool { + if (targetObjectName == _subObject->name.str()) { foundObject = std::make_shared(*_subObject); return true; diff --git a/libyul/Object.h b/libyul/Object.h index 37d802527..a095ec599 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -117,6 +117,10 @@ public: /// The path must not lead to a @a Data object (will throw in that case). std::vector pathToSubObject(YulString _qualifiedName) const; + /// Searches for a subobject at @param _qualifiedName within the current object. + /// @returns a shared_ptr to the subobject or a nullptr if it was not found. + std::shared_ptr subObjectAt(std::string const& _qualifiedName); + /// Visits all subobjects in the path given by the @a _qualifiedName /// of the current object applying the function @a _visitor. /// If @a _visitor returns `true` the visiting stops, otherwise, @@ -138,13 +142,6 @@ public: /// @returns the name of the special metadata data object. static std::string metadataName() { return ".metadata"; } - - /// Searches for an Object at @param _qualifiedName within @param _object. - /// @returns a shared_ptr to the Object or a nullptr if it was not found. - static std::shared_ptr objectAt( - std::shared_ptr const& _object, - std::string const& _qualifiedName - ); }; } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index f4be2f53b..c783a5e9f 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -253,7 +253,7 @@ public: { if (!m_inputIsCodeBlock) { - shared_ptr subObject = Object::objectAt(m_object, _objectPath); + shared_ptr subObject = m_object->subObjectAt(_objectPath); if (subObject == nullptr) solThrow(Exception, "Assembly object not found.");