aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp30
-rw-r--r--libsolidity/ast/Types.cpp2
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp56
4 files changed, 83 insertions, 6 deletions
diff --git a/Changelog.md b/Changelog.md
index bea9dd5b..dd8d6e49 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -22,6 +22,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
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 9846a0d0..1748b518 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<ArrayType const&>(_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 771ae643..6a9707f3 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;
}
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index b6e2cd43..87d62973 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -978,6 +978,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"(