diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 2aa57d7e3..2fd60f7b0 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -674,15 +674,23 @@ void FunctionCall::checkTypeRequirements() else if (OverloadedFunctionType const* overloadedTypes = dynamic_cast(expressionType)) { // this only applies to "x(3)" where x is assigned by "var x = f;" where f is an overloaded functions. - overloadedTypes->m_identifier->overloadResolution(*this); - FunctionType const* functionType = dynamic_cast(overloadedTypes->m_identifier->getType().get()); + auto identifier = dynamic_cast(m_expression.get()); + solAssert(identifier, "only applies to 'var x = f;'"); + + Declaration const* function = overloadedTypes->getIdentifier()->overloadResolution(*this); + if (!function) + BOOST_THROW_EXCEPTION(createTypeError("Can't resolve declarations")); + + identifier->setReferencedDeclaration(*function); + identifier->checkTypeRequirements(); + + TypePointer type = identifier->getType(); + FunctionType const* functionType = dynamic_cast(type.get()); - // @todo actually the return type should be an anonymous struct, - // but we change it to the type of the first return value until we have structs if (functionType->getReturnParameterTypes().empty()) m_type = make_shared(); else - m_type = functionType->getReturnParameterTypes().front(); + m_type = functionType->getReturnParameterTypes().front(); } else BOOST_THROW_EXCEPTION(createTypeError("Type is not callable.")); @@ -781,7 +789,7 @@ void Identifier::checkTypeRequirementsWithFunctionCall(FunctionCall const& _func solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved."); if (!m_referencedDeclaration) - overloadResolution(_functionCall); + setReferencedDeclaration(*overloadResolution(_functionCall)); checkTypeRequirements(); } @@ -791,7 +799,7 @@ void Identifier::checkTypeRequirementsFromVariableDeclaration() solAssert(m_referencedDeclaration || !m_overloadedDeclarations.empty(), "Identifier not resolved."); if (!m_referencedDeclaration) - m_type = make_shared(m_overloadedDeclarations, this); + m_type = make_shared(this); else checkTypeRequirements(); @@ -808,13 +816,11 @@ void Identifier::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined.")); } -void Identifier::overloadResolution(FunctionCall const& _functionCall) +Declaration const* Identifier::overloadResolution(FunctionCall const& _functionCall) { solAssert(m_overloadedDeclarations.size() > 1, "FunctionIdentifier not resolved."); solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution."); - bool resolved = false; - std::vector> arguments = _functionCall.getArguments(); std::vector> const& argumentNames = _functionCall.getNames(); @@ -844,7 +850,7 @@ void Identifier::overloadResolution(FunctionCall const& _functionCall) { return declaration->getScope() == possibles.front()->getScope(); })) - setReferencedDeclaration(*possibles.front()); + return possibles.front(); else BOOST_THROW_EXCEPTION(createTypeError("Can't resolve identifier")); } @@ -852,6 +858,7 @@ void Identifier::overloadResolution(FunctionCall const& _functionCall) // named arguments // TODO: don't support right now BOOST_THROW_EXCEPTION(createTypeError("Named arguments with overloaded functions are not supported yet.")); + return nullptr; } void ElementaryTypeNameExpression::checkTypeRequirements() diff --git a/libsolidity/AST.h b/libsolidity/AST.h index fa1d4a92e..6cc7f742f 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -1157,7 +1157,7 @@ public: void checkTypeRequirementsWithFunctionCall(FunctionCall const& _functionCall); void checkTypeRequirementsFromVariableDeclaration(); - void overloadResolution(FunctionCall const& _functionCall); + Declaration const* overloadResolution(FunctionCall const& _functionCall); private: ASTPointer m_name; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 5e5442ba3..4be461b25 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -822,11 +822,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) void ExpressionCompiler::endVisit(Identifier const& _identifier) { Declaration const* declaration = _identifier.getReferencedDeclaration(); - if (declaration == nullptr) - { - // no-op - } - else if (MagicVariableDeclaration const* magicVar = dynamic_cast(declaration)) + if (MagicVariableDeclaration const* magicVar = dynamic_cast(declaration)) { if (magicVar->getType()->getCategory() == Type::Category::Contract) // "this" or "super" @@ -849,6 +845,13 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) { // no-op } + else if (declaration == nullptr && _identifier.getOverloadedDeclarations().size() > 1) + { + // var x = f; + declaration = *_identifier.getOverloadedDeclarations().begin(); + FunctionDefinition const* functionDef = dynamic_cast(declaration); + m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag(); + } else { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context.")); diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 5dd742ada..b19f75406 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -527,13 +527,14 @@ private: class OverloadedFunctionType: public Type { public: - explicit OverloadedFunctionType(std::set const& _overloadedDeclarations, Identifier* _identifier): - m_overloadedDeclarations(_overloadedDeclarations), m_identifier(_identifier) {} + explicit OverloadedFunctionType(Identifier* _identifier): m_identifier(_identifier) {} + virtual Category getCategory() const override { return Category::OverloadedFunctions; } virtual std::string toString() const override { return "OverloadedFunctions"; } -// private: - std::set m_overloadedDeclarations; + Identifier* getIdentifier() const { return m_identifier; } + +private: Identifier * m_identifier; };