aboutsummaryrefslogtreecommitdiffstats
path: root/Types.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-04-15 23:40:50 +0800
committerchriseth <c@ethdev.com>2015-04-15 23:40:50 +0800
commit0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5 (patch)
treef78c665e6084300b939cc4cfcebb97d3bd44d9f5 /Types.cpp
parent158795e48f4285d713b11f78cdd04de8c6d1f667 (diff)
downloaddexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.tar.gz
dexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.tar.zst
dexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.zip
Fixed function overloads.
Added tests, disallowed non-calling usage of non-unique function references.
Diffstat (limited to 'Types.cpp')
-rw-r--r--Types.cpp117
1 files changed, 86 insertions, 31 deletions
diff --git a/Types.cpp b/Types.cpp
index 78649cc9..e35dc0b6 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -25,6 +25,7 @@
#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
+#include <libdevcrypto/SHA3.h>
#include <libsolidity/Utils.h>
#include <libsolidity/AST.h>
@@ -92,13 +93,13 @@ std::pair<u256, unsigned> const* MemberList::getMemberStorageOffset(string const
{
TypePointers memberTypes;
memberTypes.reserve(m_memberTypes.size());
- for (auto const& nameAndType: m_memberTypes)
- memberTypes.push_back(nameAndType.second);
+ for (auto const& member: m_memberTypes)
+ memberTypes.push_back(member.type);
m_storageOffsets.reset(new StorageOffsets());
m_storageOffsets->computeOffsets(memberTypes);
}
for (size_t index = 0; index < m_memberTypes.size(); ++index)
- if (m_memberTypes[index].first == _name)
+ if (m_memberTypes[index].name == _name)
return m_storageOffsets->getOffset(index);
return nullptr;
}
@@ -189,7 +190,7 @@ TypePointer Type::fromArrayTypeName(TypeName& _baseTypeName, Expression* _length
if (_length)
{
if (!_length->getType())
- _length->checkTypeRequirements();
+ _length->checkTypeRequirements(nullptr);
auto const* length = dynamic_cast<IntegerConstantType const*>(_length->getType().get());
if (!length)
BOOST_THROW_EXCEPTION(_length->createTypeError("Invalid array length."));
@@ -793,18 +794,46 @@ MemberList const& ContractType::getMembers() const
if (!m_members)
{
// All address members and all interface functions
- vector<pair<string, TypePointer>> members(IntegerType::AddressMemberList.begin(),
- IntegerType::AddressMemberList.end());
+ MemberList::MemberMap members(
+ IntegerType::AddressMemberList.begin(),
+ IntegerType::AddressMemberList.end()
+ );
if (m_super)
{
+ // add the most derived of all functions which are visible in derived contracts
for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts())
for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions())
- if (function->isVisibleInDerivedContracts())
- members.push_back(make_pair(function->getName(), make_shared<FunctionType>(*function, true)));
+ {
+ if (!function->isVisibleInDerivedContracts())
+ continue;
+ auto functionType = make_shared<FunctionType>(*function, true);
+ bool functionWithEqualArgumentsFound = false;
+ for (auto const& member: members)
+ {
+ if (member.name != function->getName())
+ continue;
+ auto memberType = dynamic_cast<FunctionType const*>(member.type.get());
+ solAssert(!!memberType, "Override changes type.");
+ if (!memberType->hasEqualArgumentTypes(*functionType))
+ continue;
+ functionWithEqualArgumentsFound = true;
+ break;
+ }
+ if (!functionWithEqualArgumentsFound)
+ members.push_back(MemberList::Member(
+ function->getName(),
+ functionType,
+ function.get()
+ ));
+ }
}
else
for (auto const& it: m_contract.getInterfaceFunctions())
- members.push_back(make_pair(it.second->getDeclaration().getName(), it.second));
+ members.push_back(MemberList::Member(
+ it.second->getDeclaration().getName(),
+ it.second,
+ &it.second->getDeclaration()
+ ));
m_members.reset(new MemberList(members));
}
return *m_members;
@@ -823,16 +852,6 @@ shared_ptr<FunctionType const> const& ContractType::getConstructorType() const
return m_constructorType;
}
-u256 ContractType::getFunctionIdentifier(string const& _functionName) const
-{
- auto interfaceFunctions = m_contract.getInterfaceFunctions();
- for (auto const& it: m_contract.getInterfaceFunctions())
- if (it.second->getDeclaration().getName() == _functionName)
- return FixedHash<4>::Arith(it.first);
-
- return Invalid256;
-}
-
vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::getStateVariables() const
{
vector<VariableDeclaration const*> variables;
@@ -873,8 +892,8 @@ u256 StructType::getStorageSize() const
bool StructType::canLiveOutsideStorage() const
{
- for (pair<string, TypePointer> const& member: getMembers())
- if (!member.second->canLiveOutsideStorage())
+ for (auto const& member: getMembers())
+ if (!member.type->canLiveOutsideStorage())
return false;
return true;
}
@@ -891,7 +910,7 @@ MemberList const& StructType::getMembers() const
{
MemberList::MemberMap members;
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
- members.push_back(make_pair(variable->getName(), variable->getType()));
+ members.push_back(MemberList::Member(variable->getName(), variable->getType(), variable.get()));
m_members.reset(new MemberList(members));
}
return *m_members;
@@ -996,11 +1015,11 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
vector<string> retParamNames;
if (auto structType = dynamic_cast<StructType const*>(returnType.get()))
{
- for (pair<string, TypePointer> const& member: structType->getMembers())
- if (member.second->canLiveOutsideStorage())
+ for (auto const& member: structType->getMembers())
+ if (member.type->canLiveOutsideStorage())
{
- retParamNames.push_back(member.first);
- retParams.push_back(member.second);
+ retParamNames.push_back(member.name);
+ retParams.push_back(member.type);
}
}
else
@@ -1130,12 +1149,12 @@ MemberList const& FunctionType::getMembers() const
case Location::Bare:
if (!m_members)
{
- vector<pair<string, TypePointer>> members{
+ MemberList::MemberMap members{
{"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(false, true)},
Location::SetValue, false, m_gasSet, m_valueSet)}};
if (m_location != Location::Creation)
- members.push_back(make_pair("gas", make_shared<FunctionType>(
+ members.push_back(MemberList::Member("gas", make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)},
Location::SetGas, false, m_gasSet, m_valueSet)));
@@ -1147,6 +1166,37 @@ MemberList const& FunctionType::getMembers() const
}
}
+bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes) const
+{
+ TypePointers const& parameterTypes = getParameterTypes();
+ if (takesArbitraryParameters())
+ return true;
+ else if (_argumentTypes.size() != parameterTypes.size())
+ return false;
+ else
+ return std::equal(
+ _argumentTypes.cbegin(),
+ _argumentTypes.cend(),
+ parameterTypes.cbegin(),
+ [](TypePointer const& argumentType, TypePointer const& parameterType)
+ {
+ return argumentType->isImplicitlyConvertibleTo(*parameterType);
+ }
+ );
+}
+
+bool FunctionType::hasEqualArgumentTypes(FunctionType const& _other) const
+{
+ if (m_parameterTypes.size() != _other.m_parameterTypes.size())
+ return false;
+ return equal(
+ m_parameterTypes.cbegin(),
+ m_parameterTypes.cend(),
+ _other.m_parameterTypes.cbegin(),
+ [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; }
+ );
+}
+
string FunctionType::externalSignature(std::string const& _name) const
{
std::string funcName = _name;
@@ -1167,6 +1217,11 @@ string FunctionType::externalSignature(std::string const& _name) const
return ret + ")";
}
+u256 FunctionType::externalIdentifier() const
+{
+ return FixedHash<4>::Arith(FixedHash<4>(dev::sha3(externalSignature())));
+}
+
TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
{
TypePointers pointers;
@@ -1250,7 +1305,7 @@ MemberList const& TypeType::getMembers() const
// We need to lazy-initialize it because of recursive references.
if (!m_members)
{
- vector<pair<string, TypePointer>> members;
+ MemberList::MemberMap members;
if (m_actualType->getCategory() == Category::Contract && m_currentContract != nullptr)
{
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition();
@@ -1259,14 +1314,14 @@ MemberList const& TypeType::getMembers() const
// We are accessing the type of a base contract, so add all public and protected
// members. Note that this does not add inherited functions on purpose.
for (Declaration const* decl: contract.getInheritableMembers())
- members.push_back(make_pair(decl->getName(), decl->getType()));
+ members.push_back(MemberList::Member(decl->getName(), decl->getType(), decl));
}
else if (m_actualType->getCategory() == Category::Enum)
{
EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).getEnumDefinition();
auto enumType = make_shared<EnumType>(enumDef);
for (ASTPointer<EnumValue> const& enumValue: enumDef.getMembers())
- members.push_back(make_pair(enumValue->getName(), enumType));
+ members.push_back(MemberList::Member(enumValue->getName(), enumType));
}
m_members.reset(new MemberList(members));
}