diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 49773d6f4..2592be57c 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -437,17 +437,32 @@ pair>> IRGenerator::evalua ContractDefinition const& _contract ) { + struct InheritanceOrder + { + bool operator()(ContractDefinition const* _c1, ContractDefinition const* _c2) const + { + solAssert(contains(linearizedBaseContracts, _c1) && contains(linearizedBaseContracts, _c2), ""); + auto it1 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c1); + auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2); + return it1 < it2; + } + vector const& linearizedBaseContracts; + } inheritanceOrder{_contract.annotation().linearizedBaseContracts}; + map> constructorParams; - vector>const *>> baseConstructorArguments; + + map>const *, InheritanceOrder> + baseConstructorArguments(inheritanceOrder); + ; for (ASTPointer const& base: _contract.baseContracts()) if (FunctionDefinition const* baseConstructor = dynamic_cast( base->name().annotation().referencedDeclaration )->constructor(); baseConstructor && base->arguments()) - baseConstructorArguments.emplace_back( + solAssert(baseConstructorArguments.emplace( dynamic_cast(baseConstructor->scope()), base->arguments() - ); + ).second, ""); if (FunctionDefinition const* constructor = _contract.constructor()) for (ASTPointer const& modifier: constructor->modifiers()) @@ -458,10 +473,10 @@ pair>> IRGenerator::evalua FunctionDefinition const* baseConstructor = baseContract->constructor(); baseConstructor && modifier->arguments() ) - baseConstructorArguments.emplace_back( + solAssert(baseConstructorArguments.emplace( dynamic_cast(baseConstructor->scope()), modifier->arguments() - ); + ).second, ""); IRGeneratorForStatements generator{m_context, m_utils}; for (auto&& [baseContract, arguments]: baseConstructorArguments) diff --git a/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol new file mode 100644 index 000000000..c05c2104f --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/order_of_evaluation.sol @@ -0,0 +1,24 @@ +contract A { + constructor(uint) {} +} +contract B { + constructor(uint) {} +} +contract C { + constructor(uint) {} +} +contract D { + constructor(uint) {} +} +contract X is D, C, B, A { + uint[] x; + function f(uint _x) internal returns (uint) { + x.push(_x); + } + function g() public view returns (uint[] memory) { return x; } + constructor() A(f(1)) C(f(2)) B(f(3)) D(f(4)) {} +} +// ==== +// compileViaYul: also +// ---- +// g() -> 0x20, 4, 1, 3, 2, 4