diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 908e1d48c..c7a873e60 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -579,32 +579,60 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) else args.emplace_back(convert(*arguments[i], *parameterTypes[i]).commaSeparatedList()); - if (auto identifier = dynamic_cast(&_functionCall.expression())) + optional functionDef; + if (auto memberAccess = dynamic_cast(&_functionCall.expression())) { solAssert(!functionType->bound(), ""); - if (auto functionDef = dynamic_cast(identifier->annotation().referencedDeclaration)) + + functionDef = dynamic_cast(memberAccess->annotation().referencedDeclaration); + if (functionDef.value() != nullptr) + solAssert(functionType->declaration() == *memberAccess->annotation().referencedDeclaration, ""); + else { - define(_functionCall) << - m_context.enqueueFunctionForCodeGeneration( - functionDef->resolveVirtual(m_context.mostDerivedContract()) - ) << - "(" << - joinHumanReadable(args) << - ")\n"; - return; + solAssert(dynamic_cast(memberAccess->annotation().referencedDeclaration), ""); + solAssert(!functionType->hasDeclaration(), ""); } } + else if (auto identifier = dynamic_cast(&_functionCall.expression())) + { + solAssert(!functionType->bound(), ""); - define(_functionCall) << - // NOTE: internalDispatch() takes care of adding the function to function generation queue - m_context.internalDispatch( - TupleType(functionType->parameterTypes()).sizeOnStack(), - TupleType(functionType->returnParameterTypes()).sizeOnStack() - ) << - "(" << - IRVariable(_functionCall.expression()).part("functionIdentifier").name() << - joinHumanReadablePrefixed(args) << - ")\n"; + if (auto unresolvedFunctionDef = dynamic_cast(identifier->annotation().referencedDeclaration)) + { + functionDef = &unresolvedFunctionDef->resolveVirtual(m_context.mostDerivedContract()); + solAssert(functionType->declaration() == *identifier->annotation().referencedDeclaration, ""); + } + else + { + functionDef = nullptr; + solAssert(dynamic_cast(identifier->annotation().referencedDeclaration), ""); + solAssert(!functionType->hasDeclaration(), ""); + } + } + else + // Not a simple expression like x or A.x + functionDef = nullptr; + + solAssert(functionDef.has_value(), ""); + solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), ""); + + if (functionDef.value() != nullptr) + define(_functionCall) << + m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) << + "(" << + joinHumanReadable(args) << + ")\n"; + else + define(_functionCall) << + // NOTE: internalDispatch() takes care of adding the function to function generation queue + m_context.internalDispatch( + TupleType(functionType->parameterTypes()).sizeOnStack(), + TupleType(functionType->returnParameterTypes()).sizeOnStack() + ) << + "(" << + IRVariable(_functionCall.expression()).part("functionIdentifier").name() << + joinHumanReadablePrefixed(args) << + ")\n"; break; } case FunctionType::Kind::External: diff --git a/test/libsolidity/semanticTests/functionCall/base_base_overload.sol b/test/libsolidity/semanticTests/functionCall/base_base_overload.sol index adf1200ee..c1ba1c1ff 100644 --- a/test/libsolidity/semanticTests/functionCall/base_base_overload.sol +++ b/test/libsolidity/semanticTests/functionCall/base_base_overload.sol @@ -34,6 +34,8 @@ contract Child is Base { BaseBase.init(c, d); } } +// ==== +// compileViaYul: also // ---- // x() -> 0 // y() -> 0 diff --git a/test/libsolidity/semanticTests/functionCall/base_overload.sol b/test/libsolidity/semanticTests/functionCall/base_overload.sol index 924431ec5..be4a73809 100644 --- a/test/libsolidity/semanticTests/functionCall/base_overload.sol +++ b/test/libsolidity/semanticTests/functionCall/base_overload.sol @@ -18,6 +18,8 @@ contract Child is Base { Base.init(c, d); } } +// ==== +// compileViaYul: also // ---- // x() -> 0 // y() -> 0