From 754076319659a387a2c447fe69285aad07e0abb6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 19 Feb 2018 18:20:49 +0100 Subject: [PATCH 1/3] Tests for multi-dimensional arrays. --- .../SolidityNameAndTypeResolution.cpp | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 8c2d853ce..1fadcbde6 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -979,6 +979,62 @@ BOOST_AUTO_TEST_CASE(functions_with_stucts_of_non_external_types_in_interface_ne CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); } +BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays_new_abi) +{ + char const* text = R"( + pragma experimental ABIEncoderV2; + + contract C { + function f() public pure returns (string[][]) {} + } + )"; + CHECK_WARNING(text, "Experimental features"); +} + +BOOST_AUTO_TEST_CASE(returning_multi_dimensional_arrays) +{ + char const* text = R"( + contract C { + function f() public pure returns (string[][]) {} + } + )"; + CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); +} + +BOOST_AUTO_TEST_CASE(returning_multi_dimensional_static_arrays) +{ + char const* text = R"( + contract C { + function f() public pure returns (uint[][2]) {} + } + )"; + CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); +} + +BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_new_abi) +{ + char const* text = R"( + pragma experimental ABIEncoderV2; + + contract C { + struct S { string[] s; } + function f() public pure returns (S) {} + } + )"; + CHECK_WARNING(text, "Experimental features"); +} + +BOOST_AUTO_TEST_CASE(returning_arrays_in_structs_arrays) +{ + char const* text = R"( + contract C { + struct S { string[] s; } + function f() public pure returns (S x) {} + } + )"; + CHECK_ERROR(text, TypeError, "only supported in the new experimental ABI encoder"); +} + BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) { char const* text = R"( From 08b6a72d37f4e4149575bfc695d76c61b666a8a9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 19 Feb 2018 18:21:02 +0100 Subject: [PATCH 2/3] Fix multi-dimensional arrays in the ABI. --- libsolidity/analysis/TypeChecker.cpp | 30 ++++++++++++++++++++++++---- libsolidity/ast/Types.cpp | 2 -- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 2914472af..a2d94be48 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -34,6 +34,29 @@ using namespace std; using namespace dev; using namespace dev::solidity; +namespace +{ + +bool typeSupportedByOldABIEncoder(Type const& _type) +{ + if (_type.dataStoredIn(DataLocation::Storage)) + return true; + else if (_type.category() == Type::Category::Struct) + return false; + else if (_type.category() == Type::Category::Array) + { + auto const& arrayType = dynamic_cast(_type); + auto base = arrayType.baseType(); + if (!typeSupportedByOldABIEncoder(*base)) + return false; + else if (base->category() == Type::Category::Array && base->isDynamicallySized()) + return false; + } + return true; +} + +} + bool TypeChecker::checkTypeRequirements(ASTNode const& _contract) { @@ -561,13 +584,12 @@ bool TypeChecker::visit(FunctionDefinition const& _function) m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions."); if ( _function.visibility() > FunctionDefinition::Visibility::Internal && - type(*var)->category() == Type::Category::Struct && - !type(*var)->dataStoredIn(DataLocation::Storage) && - !_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) + !_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && + !typeSupportedByOldABIEncoder(*type(*var)) ) m_errorReporter.typeError( var->location(), - "Structs are only supported in the new experimental ABI encoder. " + "This type is only supported in the new experimental ABI encoder. " "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." ); diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 771ae6439..6a9707f3e 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1589,8 +1589,6 @@ bool ArrayType::canBeUsedExternally(bool _inLibrary) const return true; else if (!m_baseType->canBeUsedExternally(_inLibrary)) return false; - else if (m_baseType->category() == Category::Array && m_baseType->isDynamicallySized()) - return false; else return true; } From 98e8a9385456b5d3fe3ca7ef2e0c923b0aab2ea3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 19 Feb 2018 18:45:42 +0100 Subject: [PATCH 3/3] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 4262f8397..ebdb2e4ed 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Bugfixes: * Standalone Assembly: Do not ignore input after closing brace of top level block. * Standard JSON: Catch errors properly when invalid "sources" are passed. * Standard JSON: Ensure that library addresses supplied are of correct length and hex prefixed. + * Type Checker: Properly detect which array and struct types are unsupported by the old ABI encoder. * Type Checker: Properly warn when using ``_offset`` and ``_slot`` for constants in inline assembly. * Commandline interface: throw error if option is unknown