diff options
-rw-r--r-- | libsolidity/ast/Types.cpp | 23 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 23 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 19 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 2 |
4 files changed, 50 insertions, 17 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index e964d683..5630743b 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2037,29 +2037,20 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) location = Location::DelegateCall; } - TypePointers returnParameterTypes; - vector<string> returnParameterNames; - if (location == Location::Internal) + TypePointers returnParameterTypes = m_returnParameterTypes; + if (location != Location::Internal) { - returnParameterNames = m_returnParameterNames; - returnParameterTypes = m_returnParameterTypes; - } - else - { - // Removes dynamic types. - for (size_t i = 0; i < m_returnParameterTypes.size(); ++i) - if (!m_returnParameterTypes[i]->isDynamicallySized()) - { - returnParameterTypes.push_back(m_returnParameterTypes[i]); - returnParameterNames.push_back(m_returnParameterNames[i]); - } + // Alter dynamic types to be non-accessible. + for (auto& param: returnParameterTypes) + if (param->isDynamicallySized()) + param = make_shared<InaccessibleDynamicType>(); } return make_shared<FunctionType>( parameterTypes, returnParameterTypes, m_parameterNames, - returnParameterNames, + m_returnParameterNames, location, m_arbitraryParameters, m_declaration, diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 967e968c..1ee762e5 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -137,7 +137,8 @@ public: { Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array, FixedBytes, Contract, Struct, Function, Enum, Tuple, - Mapping, TypeType, Modifier, Magic, Module + Mapping, TypeType, Modifier, Magic, Module, + InaccessibleDynamic }; /// @{ @@ -1081,5 +1082,25 @@ private: Kind m_kind; }; +/** + * Special type that is used for dynamic types in returns from external function calls + * (The EVM currently cannot access dynamically-sized return values). + */ +class InaccessibleDynamicType: public Type +{ +public: + virtual Category category() const override { return Category::InaccessibleDynamic; } + + virtual bool isImplicitlyConvertibleTo(Type const&) const override { return false; } + virtual bool isExplicitlyConvertibleTo(Type const&) const override { return false; } + virtual unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; } + virtual bool canBeStored() const override { return false; } + virtual bool canLiveOutsideStorage() const override { return false; } + virtual bool isValueType() const override { return true; } + virtual unsigned sizeOnStack() const override { return 1; } + virtual std::string toString(bool) const override { return "inaccessible dynamic type"; } + virtual TypePointer decodingType() const override { return std::make_shared<IntegerType>(256); } +}; + } } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 30ae5792..9b97b916 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6793,6 +6793,25 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) BOOST_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)) == encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(skip_dynamic_types) +{ + // The EVM cannot provide access to dynamically-sized return values, so we have to skip them. + char const* sourceCode = R"( + contract C { + function f() returns (uint, uint[], uint) { + return (7, new uint[](2), 8); + } + function g() returns (uint, uint) { + // Previous implementation "moved" b to the second place and did not skip. + var (a, _, b) = this.f(); + return (a, b); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(7), u256(8))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 52e0bf58..3b148c9a 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2154,6 +2154,8 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) function f(uint) returns (string); function g() { var (x,) = this.f(2); + // we can assign to x but it is not usable. + bytes(x).length; } } )"; |