diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/Types.cpp | 90 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 28 | ||||
-rw-r--r-- | libsolidity/interface/ABI.cpp | 5 |
3 files changed, 84 insertions, 39 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 44316403..9fdfe632 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -33,6 +33,7 @@ #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/range/adaptor/reversed.hpp> +#include <boost/range/algorithm/copy.hpp> #include <boost/range/adaptor/sliced.hpp> #include <boost/range/adaptor/transformed.hpp> @@ -1470,7 +1471,7 @@ string ArrayType::toString(bool _short) const return ret; } -string ArrayType::canonicalName(bool _addDataLocation) const +string ArrayType::canonicalName() const { string ret; if (isString()) @@ -1479,16 +1480,29 @@ string ArrayType::canonicalName(bool _addDataLocation) const ret = "bytes"; else { - ret = baseType()->canonicalName(false) + "["; + ret = baseType()->canonicalName() + "["; if (!isDynamicallySized()) ret += length().str(); ret += "]"; } - if (_addDataLocation && location() == DataLocation::Storage) - ret += " storage"; return ret; } +string ArrayType::signatureInExternalFunction(bool _structsByName) const +{ + if (isByteArray()) + return canonicalName(); + else + { + solAssert(baseType(), ""); + return + baseType()->signatureInExternalFunction(_structsByName) + + "[" + + (isDynamicallySized() ? "" : length().str()) + + "]"; + } +} + MemberList::MemberMap ArrayType::nativeMembers(ContractDefinition const*) const { MemberList::MemberMap members; @@ -1597,7 +1611,7 @@ string ContractType::toString(bool) const m_contract.name(); } -string ContractType::canonicalName(bool) const +string ContractType::canonicalName() const { return m_contract.annotation().canonicalName; } @@ -1727,9 +1741,8 @@ bool StructType::isDynamicallyEncoded() const u256 StructType::memorySize() const { u256 size; - for (auto const& member: members(nullptr)) - if (member.type->canLiveOutsideStorage()) - size += member.type->memoryHeadSize(); + for (auto const& t: memoryMemberTypes()) + size += t->memoryHeadSize(); return size; } @@ -1782,12 +1795,25 @@ TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) return copy; } -string StructType::canonicalName(bool _addDataLocation) const +string StructType::signatureInExternalFunction(bool _structsByName) const { - string ret = m_struct.annotation().canonicalName; - if (_addDataLocation && location() == DataLocation::Storage) - ret += " storage"; - return ret; + if (_structsByName) + return canonicalName(); + else + { + TypePointers memberTypes = memoryMemberTypes(); + auto memberTypeStrings = memberTypes | boost::adaptors::transformed([&](TypePointer _t) -> string + { + solAssert(_t, "Parameter should have external type."); + return _t->signatureInExternalFunction(_structsByName); + }); + return "(" + boost::algorithm::join(memberTypeStrings, ",") + ")"; + } +} + +string StructType::canonicalName() const +{ + return m_struct.annotation().canonicalName; } FunctionTypePointer StructType::constructorType() const @@ -1829,6 +1855,15 @@ u256 StructType::memoryOffsetOfMember(string const& _name) const return 0; } +TypePointers StructType::memoryMemberTypes() const +{ + TypePointers types; + for (ASTPointer<VariableDeclaration> const& variable: m_struct.members()) + if (variable->annotation().type->canLiveOutsideStorage()) + types.push_back(variable->annotation().type); + return types; +} + set<string> StructType::membersMissingInMemory() const { set<string> missing; @@ -1893,7 +1928,7 @@ string EnumType::toString(bool) const return string("enum ") + m_enum.annotation().canonicalName; } -string EnumType::canonicalName(bool) const +string EnumType::canonicalName() const { return m_enum.annotation().canonicalName; } @@ -2320,7 +2355,7 @@ TypePointer FunctionType::binaryOperatorResult(Token::Value _operator, TypePoint return TypePointer(); } -string FunctionType::canonicalName(bool) const +string FunctionType::canonicalName() const { solAssert(m_kind == Kind::External, ""); return "function"; @@ -2580,20 +2615,19 @@ string FunctionType::externalSignature() const solAssert(m_declaration != nullptr, "External signature of function needs declaration"); solAssert(!m_declaration->name().empty(), "Fallback function has no signature."); - bool _inLibrary = dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary(); - - string ret = m_declaration->name() + "("; - + bool const inLibrary = dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary(); FunctionTypePointer external = interfaceFunctionType(); solAssert(!!external, "External function type requested."); - TypePointers externalParameterTypes = external->parameterTypes(); - for (auto it = externalParameterTypes.cbegin(); it != externalParameterTypes.cend(); ++it) + auto parameterTypes = external->parameterTypes(); + auto typeStrings = parameterTypes | boost::adaptors::transformed([&](TypePointer _t) -> string { - solAssert(!!(*it), "Parameter should have external type"); - ret += (*it)->canonicalName(_inLibrary) + (it + 1 == externalParameterTypes.cend() ? "" : ","); - } - - return ret + ")"; + solAssert(_t, "Parameter should have external type."); + string typeName = _t->signatureInExternalFunction(inLibrary); + if (inLibrary && _t->dataStoredIn(DataLocation::Storage)) + typeName += " storage"; + return typeName; + }); + return m_declaration->name() + "(" + boost::algorithm::join(typeStrings, ",") + ")"; } u256 FunctionType::externalIdentifier() const @@ -2724,9 +2758,9 @@ string MappingType::toString(bool _short) const return "mapping(" + keyType()->toString(_short) + " => " + valueType()->toString(_short) + ")"; } -string MappingType::canonicalName(bool) const +string MappingType::canonicalName() const { - return "mapping(" + keyType()->canonicalName(false) + " => " + valueType()->canonicalName(false) + ")"; + return "mapping(" + keyType()->canonicalName() + " => " + valueType()->canonicalName() + ")"; } string TypeType::identifier() const diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index e6d3a7b1..0713f527 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -245,9 +245,15 @@ public: virtual std::string toString(bool _short) const = 0; std::string toString() const { return toString(false); } - /// @returns the canonical name of this type for use in function signatures. - /// @param _addDataLocation if true, includes data location for reference types if it is "storage". - virtual std::string canonicalName(bool /*_addDataLocation*/) const { return toString(true); } + /// @returns the canonical name of this type for use in library function signatures. + virtual std::string canonicalName() const { return toString(true); } + /// @returns the signature of this type in external functions, i.e. `uint256` for integers + /// or `(uint256, bytes8)[2]` for an array of structs. If @a _structsByName, + /// structs are given by canonical name like `ContractName.StructName[2]`. + virtual std::string signatureInExternalFunction(bool /*_structsByName*/) const + { + return canonicalName(); + } virtual u256 literalValue(Literal const*) const { solAssert(false, "Literal value requested for type without literals."); @@ -619,7 +625,8 @@ public: virtual bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); } virtual unsigned sizeOnStack() const override; virtual std::string toString(bool _short) const override; - virtual std::string canonicalName(bool _addDataLocation) const override; + virtual std::string canonicalName() const override; + virtual std::string signatureInExternalFunction(bool _structsByName) const override; virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; virtual TypePointer encodingType() const override; virtual TypePointer decodingType() const override; @@ -677,7 +684,7 @@ public: virtual unsigned sizeOnStack() const override { return m_super ? 0 : 1; } virtual bool isValueType() const override { return true; } virtual std::string toString(bool _short) const override; - virtual std::string canonicalName(bool _addDataLocation) const override; + virtual std::string canonicalName() const override; virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; virtual TypePointer encodingType() const override @@ -744,7 +751,8 @@ public: TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; - virtual std::string canonicalName(bool _addDataLocation) const override; + virtual std::string canonicalName() const override; + virtual std::string signatureInExternalFunction(bool _structsByName) const override; /// @returns a function that peforms the type conversion between a list of struct members /// and a memory struct of this type. @@ -755,6 +763,8 @@ public: StructDefinition const& structDefinition() const { return m_struct; } + /// @returns the vector of types of members available in memory. + TypePointers memoryMemberTypes() const; /// @returns the set of all members that are removed in the memory version (typically mappings). std::set<std::string> membersMissingInMemory() const; @@ -784,7 +794,7 @@ public: virtual unsigned storageBytes() const override; virtual bool canLiveOutsideStorage() const override { return true; } virtual std::string toString(bool _short) const override; - virtual std::string canonicalName(bool _addDataLocation) const override; + virtual std::string canonicalName() const override; virtual bool isValueType() const override { return true; } virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; @@ -955,7 +965,7 @@ public: virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override; - virtual std::string canonicalName(bool /*_addDataLocation*/) const override; + virtual std::string canonicalName() const override; virtual std::string toString(bool _short) const override; virtual unsigned calldataEncodedSize(bool _padded) const override; virtual bool canBeStored() const override { return m_kind == Kind::Internal || m_kind == Kind::External; } @@ -1057,7 +1067,7 @@ public: virtual std::string identifier() const override; virtual bool operator==(Type const& _other) const override; virtual std::string toString(bool _short) const override; - virtual std::string canonicalName(bool _addDataLocation) const override; + virtual std::string canonicalName() const override; virtual bool canLiveOutsideStorage() const override { return false; } virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } virtual TypePointer encodingType() const override diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index 7c7496cd..c04de57e 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -120,12 +120,13 @@ Json::Value ABI::formatType(string const& _name, Type const& _type, bool _forLib { Json::Value ret; ret["name"] = _name; + string suffix = (_forLibrary && _type.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; if (_type.isValueType() || (_forLibrary && _type.dataStoredIn(DataLocation::Storage))) - ret["type"] = _type.canonicalName(_forLibrary); + ret["type"] = _type.canonicalName() + suffix; else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_type)) { if (arrayType->isByteArray()) - ret["type"] = _type.canonicalName(_forLibrary); + ret["type"] = _type.canonicalName() + suffix; else { string suffix; |