diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index b711758d6..d9425937f 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -217,6 +217,37 @@ ContractDefinitionAnnotation& ContractDefinition::annotation() const return initAnnotation(); } +ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const +{ + auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts; + auto it = find(hierarchy.begin(), hierarchy.end(), this); + solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy."); + ++it; + if (it == hierarchy.end()) + return nullptr; + else + { + solAssert(*it != this, ""); + return *it; + } +} + +FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const +{ + ContractDefinition const* next = superContract(_mostDerivedContract); + if (next == nullptr) + return nullptr; + for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts) + if (c == next || next == nullptr) + { + if (c->constructor()) + return c->constructor(); + next = nullptr; + } + + return nullptr; +} + TypeNameAnnotation& TypeName::annotation() const { return initAnnotation(); diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 4979d5d4e..b1328d008 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -518,6 +518,10 @@ public: bool abstract() const { return m_abstract; } + ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const; + /// @returns the next constructor in the inheritance hierarchy. + FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const; + private: std::vector> m_baseContracts; std::vector> m_subNodes; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 06080afbd..2b4a888ee 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -269,29 +269,11 @@ evmasm::AssemblyItem CompilerContext::functionEntryLabelIfExists(Declaration con FunctionDefinition const& CompilerContext::superFunction(FunctionDefinition const& _function, ContractDefinition const& _base) { solAssert(m_mostDerivedContract, "No most derived contract set."); - ContractDefinition const* super = superContract(_base); + ContractDefinition const* super = _base.superContract(mostDerivedContract()); solAssert(super, "Super contract not available."); return _function.resolveVirtual(mostDerivedContract(), super); } -FunctionDefinition const* CompilerContext::nextConstructor(ContractDefinition const& _contract) const -{ - ContractDefinition const* next = superContract(_contract); - if (next == nullptr) - return nullptr; - for (ContractDefinition const* c: m_mostDerivedContract->annotation().linearizedBaseContracts) - if (next != nullptr && next != c) - continue; - else - { - next = nullptr; - if (c->constructor()) - return c->constructor(); - } - - return nullptr; -} - ContractDefinition const& CompilerContext::mostDerivedContract() const { solAssert(m_mostDerivedContract, "Most derived contract not set."); @@ -536,21 +518,6 @@ LinkerObject const& CompilerContext::assembledObject() const return object; } -ContractDefinition const* CompilerContext::superContract(ContractDefinition const& _contract) const -{ - auto const& hierarchy = mostDerivedContract().annotation().linearizedBaseContracts; - auto it = find(hierarchy.begin(), hierarchy.end(), &_contract); - solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy."); - ++it; - if (it == hierarchy.end()) - return nullptr; - else - { - solAssert(*it != &_contract, ""); - return *it; - } -} - string CompilerContext::revertReasonIfDebug(string const& _message) { return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index a8e494435..0720a8f3b 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -117,8 +117,6 @@ public: /// @returns the function that overrides the given declaration from the most derived class just /// above _base in the current inheritance hierarchy. FunctionDefinition const& superFunction(FunctionDefinition const& _function, ContractDefinition const& _base); - /// @returns the next constructor in the inheritance hierarchy. - FunctionDefinition const* nextConstructor(ContractDefinition const& _contract) const; /// Sets the contract currently being compiled - the most derived one. void setMostDerivedContract(ContractDefinition const& _contract) { m_mostDerivedContract = &_contract; } ContractDefinition const& mostDerivedContract() const; @@ -313,8 +311,6 @@ public: RevertStrings revertStrings() const { return m_revertStrings; } private: - /// @returns a pointer to the contract directly above the given contract. - ContractDefinition const* superContract(ContractDefinition const& _contract) const; /// Updates source location set in the assembly. void updateSourceLocation(); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 822ce3b66..a599de6a4 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -159,7 +159,7 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c if (FunctionDefinition const* constructor = _contract.constructor()) appendConstructor(*constructor); - else if (auto c = m_context.nextConstructor(_contract)) + else if (auto c = _contract.nextConstructor(m_context.mostDerivedContract())) appendBaseConstructor(*c); else appendCallValueCheck(); @@ -596,7 +596,9 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) appendStackVariableInitialisation(*variable); if (_function.isConstructor()) - if (auto c = m_context.nextConstructor(dynamic_cast(*_function.scope()))) + if (auto c = dynamic_cast(*_function.scope()).nextConstructor( + m_context.mostDerivedContract() + )) appendBaseConstructor(*c); solAssert(m_returnTags.empty(), "");