diff options
author | chriseth <c@ethdev.com> | 2015-04-15 23:40:50 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-04-15 23:40:50 +0800 |
commit | 0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5 (patch) | |
tree | f78c665e6084300b939cc4cfcebb97d3bd44d9f5 /Types.cpp | |
parent | 158795e48f4285d713b11f78cdd04de8c6d1f667 (diff) | |
download | dexon-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.cpp | 117 |
1 files changed, 86 insertions, 31 deletions
@@ -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)); } |