mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fix function calls with named arguments for overloaded functions
This commit is contained in:
@@ -23,8 +23,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/ast/ASTForward.h>
|
||||
#include <libsolidity/ast/ASTEnums.h>
|
||||
#include <libsolidity/ast/ExperimentalFeatures.h>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -176,9 +179,10 @@ struct ExpressionAnnotation: ASTAnnotation
|
||||
bool isLValue = false;
|
||||
/// Whether the expression is used in a context where the LValue is actually required.
|
||||
bool lValueRequested = false;
|
||||
/// Types of arguments if the expression is a function that is called - used
|
||||
/// for overload resolution.
|
||||
std::shared_ptr<std::vector<TypePointer>> argumentTypes;
|
||||
|
||||
/// Types and - if given - names of arguments if the expr. is a function
|
||||
/// that is called, used for overload resoultion
|
||||
boost::optional<FuncCallArguments> arguments;
|
||||
};
|
||||
|
||||
struct IdentifierAnnotation: ExpressionAnnotation
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <libsolidity/ast/ASTForward.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -50,5 +51,20 @@ inline std::string stateMutabilityToString(StateMutability const& _stateMutabili
|
||||
}
|
||||
}
|
||||
|
||||
class Type;
|
||||
|
||||
/// Container for function call parameter types & names
|
||||
struct FuncCallArguments
|
||||
{
|
||||
/// Types of arguments
|
||||
std::vector<std::shared_ptr<Type const>> types;
|
||||
/// Names of the arguments if given, otherwise unset
|
||||
std::vector<ASTPointer<ASTString>> names;
|
||||
|
||||
size_t numArguments() const { return types.size(); }
|
||||
size_t numNames() const { return names.size(); }
|
||||
bool hasNamedArguments() const { return !names.empty(); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,12 +144,12 @@ Json::Value ASTJsonConverter::typePointerToJson(TypePointer _tp, bool _short)
|
||||
return typeDescriptions;
|
||||
|
||||
}
|
||||
Json::Value ASTJsonConverter::typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps)
|
||||
Json::Value ASTJsonConverter::typePointerToJson(boost::optional<FuncCallArguments> const& _tps)
|
||||
{
|
||||
if (_tps)
|
||||
{
|
||||
Json::Value arguments(Json::arrayValue);
|
||||
for (auto const& tp: *_tps)
|
||||
for (auto const& tp: _tps->types)
|
||||
appendMove(arguments, typePointerToJson(tp));
|
||||
return arguments;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void ASTJsonConverter::appendExpressionAttributes(
|
||||
make_pair("isPure", _annotation.isPure),
|
||||
make_pair("isLValue", _annotation.isLValue),
|
||||
make_pair("lValueRequested", _annotation.lValueRequested),
|
||||
make_pair("argumentTypes", typePointerToJson(_annotation.argumentTypes))
|
||||
make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
|
||||
};
|
||||
_attributes += exprAttributes;
|
||||
}
|
||||
@@ -701,7 +701,7 @@ bool ASTJsonConverter::visit(Identifier const& _node)
|
||||
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
|
||||
make_pair("overloadedDeclarations", overloads),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
|
||||
make_pair("argumentTypes", typePointerToJson(_node.annotation().argumentTypes))
|
||||
make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ private:
|
||||
return tmp;
|
||||
}
|
||||
static Json::Value typePointerToJson(TypePointer _tp, bool _short = false);
|
||||
static Json::Value typePointerToJson(std::shared_ptr<std::vector<TypePointer>> _tps);
|
||||
static Json::Value typePointerToJson(boost::optional<FuncCallArguments> const& _tps);
|
||||
void appendExpressionAttributes(
|
||||
std::vector<std::pair<std::string, Json::Value>> &_attributes,
|
||||
ExpressionAnnotation const& _annotation
|
||||
|
||||
@@ -2986,26 +2986,53 @@ TypePointer FunctionType::interfaceType(bool /*_inLibrary*/) const
|
||||
return TypePointer();
|
||||
}
|
||||
|
||||
bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes, TypePointer const& _selfType) const
|
||||
bool FunctionType::canTakeArguments(
|
||||
FuncCallArguments const& _arguments,
|
||||
TypePointer const& _selfType
|
||||
) const
|
||||
{
|
||||
solAssert(!bound() || _selfType, "");
|
||||
if (bound() && !_selfType->isImplicitlyConvertibleTo(*selfType()))
|
||||
return false;
|
||||
TypePointers paramTypes = parameterTypes();
|
||||
std::vector<std::string> const paramNames = parameterNames();
|
||||
|
||||
if (takesArbitraryParameters())
|
||||
return true;
|
||||
else if (_argumentTypes.size() != paramTypes.size())
|
||||
else if (_arguments.numArguments() != paramTypes.size())
|
||||
return false;
|
||||
else
|
||||
else if (!_arguments.hasNamedArguments())
|
||||
return equal(
|
||||
_argumentTypes.cbegin(),
|
||||
_argumentTypes.cend(),
|
||||
_arguments.types.cbegin(),
|
||||
_arguments.types.cend(),
|
||||
paramTypes.cbegin(),
|
||||
[](TypePointer const& argumentType, TypePointer const& parameterType)
|
||||
{
|
||||
return argumentType->isImplicitlyConvertibleTo(*parameterType);
|
||||
}
|
||||
);
|
||||
else if (paramNames.size() != _arguments.numNames())
|
||||
return false;
|
||||
else
|
||||
{
|
||||
solAssert(_arguments.numArguments() == _arguments.numNames(), "Expected equal sized type & name vectors");
|
||||
|
||||
size_t matchedNames = 0;
|
||||
|
||||
for (auto const& argName: _arguments.names)
|
||||
for (size_t i = 0; i < paramNames.size(); i++)
|
||||
if (*argName == paramNames[i])
|
||||
{
|
||||
matchedNames++;
|
||||
if (!_arguments.types[i]->isImplicitlyConvertibleTo(*paramTypes[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchedNames == _arguments.numNames())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const
|
||||
|
||||
@@ -1107,11 +1107,15 @@ public:
|
||||
/// external type.
|
||||
FunctionTypePointer interfaceFunctionType() const;
|
||||
|
||||
/// @returns true if this function can take the given argument types (possibly
|
||||
/// @returns true if this function can take the given arguments (possibly
|
||||
/// after implicit conversion).
|
||||
/// @param _selfType if the function is bound, this has to be supplied and is the type of the
|
||||
/// expression the function is called on.
|
||||
bool canTakeArguments(TypePointers const& _arguments, TypePointer const& _selfType = TypePointer()) const;
|
||||
bool canTakeArguments(
|
||||
FuncCallArguments const& _arguments,
|
||||
TypePointer const& _selfType = TypePointer()
|
||||
) const;
|
||||
|
||||
/// @returns true if the types of parameters are equal (does not check return parameter types)
|
||||
bool hasEqualParameterTypes(FunctionType const& _other) const;
|
||||
/// @returns true iff the return types are equal (does not check parameter types)
|
||||
|
||||
Reference in New Issue
Block a user