diff options
-rw-r--r-- | Changelog.md | 2 | ||||
-rw-r--r-- | libdevcore/Exceptions.h | 3 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 5 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 2 | ||||
-rw-r--r-- | libsolidity/interface/Exceptions.cpp | 14 | ||||
-rwxr-xr-x | scripts/uniqueErrors.sh | 14 | ||||
-rw-r--r-- | solc/jsonCompiler.cpp | 6 | ||||
-rw-r--r-- | test/fuzzer.cpp | 3 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 30 |
9 files changed, 73 insertions, 6 deletions
diff --git a/Changelog.md b/Changelog.md index c46ba3bd..5eb1e401 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,8 @@ Bugfixes: * Type system: Fix a crash caused by continuing on fatal errors in the code. * Type system: Disallow arrays with negative length. * Type system: Fix a crash related to invalid binary operators. + * Type system: Disallow ``var`` declaration with empty tuple type. + * Type system: Correctly convert function argument types to pointers for member functions. * Inline assembly: Charge one stack slot for non-value types during analysis. * Assembly output: Print source location before the operation it refers to instead of after. diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index 4622774a..37cdbed9 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -41,6 +41,9 @@ struct Exception: virtual std::exception, virtual boost::exception Exception(std::string _message = std::string()): m_message(std::move(_message)) {} const char* what() const noexcept override { return m_message.empty() ? std::exception::what() : m_message.c_str(); } + /// @returns "FileName:LineNumber" referring to the point where the exception was thrown. + std::string lineInfo() const; + private: std::string m_message; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4025831e..ff55ef1f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -824,6 +824,11 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) else solAssert(false, ""); } + else if (*var.annotation().type == TupleType()) + typeError( + var.location(), + "Cannot declare variable with void (empty tuple) type." + ); var.accept(*this); } else diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 99d6f4a2..7f267cc9 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2493,7 +2493,7 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) { auto refType = dynamic_cast<ReferenceType const*>(t.get()); if (refType && refType->location() == DataLocation::CallData) - parameterTypes.push_back(refType->copyForLocation(DataLocation::Memory, false)); + parameterTypes.push_back(refType->copyForLocation(DataLocation::Memory, true)); else parameterTypes.push_back(t); } diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp index 90a680b4..41890b91 100644 --- a/libsolidity/interface/Exceptions.cpp +++ b/libsolidity/interface/Exceptions.cpp @@ -23,6 +23,7 @@ #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/Utils.h> +using namespace std; using namespace dev; using namespace dev::solidity; @@ -56,3 +57,16 @@ Error::Error(Type _type): m_type(_type) break; } } + +string Exception::lineInfo() const +{ + char const* const* file = boost::get_error_info<boost::throw_file>(*this); + int const* line = boost::get_error_info<boost::throw_line>(*this); + string ret; + if (file) + ret += *file; + ret += ':'; + if (line) + ret += boost::lexical_cast<string>(*line); + return ret; +} diff --git a/scripts/uniqueErrors.sh b/scripts/uniqueErrors.sh new file mode 100755 index 00000000..eee1df90 --- /dev/null +++ b/scripts/uniqueErrors.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +REPO=$(dirname $0)/.. + +echo "Finding unique failures..." +( +for x in $* +do + echo -n $x " # " + # This subshell is a workaround to prevent the shell from printing + # "Aborted" + ("$REPO"/build/test/solfuzzer < "$x" || true) 2>&1 | head -n 1 +done +) | sort -u -t'#' -k 2 diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index d761b541..6ebd1a55 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -184,15 +184,15 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback } catch (CompilerError const& exception) { - errors.append(formatError(exception, "Compiler error", scannerFromSourceName)); + errors.append(formatError(exception, "Compiler error (" + exception.lineInfo() + ")", scannerFromSourceName)); } catch (InternalCompilerError const& exception) { - errors.append(formatError(exception, "Internal compiler error", scannerFromSourceName)); + errors.append(formatError(exception, "Internal compiler error (" + exception.lineInfo() + ")", scannerFromSourceName)); } catch (UnimplementedFeatureError const& exception) { - errors.append(formatError(exception, "Unimplemented feature", scannerFromSourceName)); + errors.append(formatError(exception, "Unimplemented feature (" + exception.lineInfo() + ")", scannerFromSourceName)); } catch (Exception const& exception) { diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp index 85a8fe99..410313c5 100644 --- a/test/fuzzer.cpp +++ b/test/fuzzer.cpp @@ -67,7 +67,6 @@ int main() for (Json::Value const& error: outputJson["errors"]) { string invalid = contains(error.asString(), vector<string>{ - "Compiler error", "Internal compiler error", "Exception during compilation", "Unknown exception during compilation", @@ -78,7 +77,7 @@ int main() }); if (!invalid.empty()) { - cout << "Invalid error: \"" << invalid << "\"" << endl; + cout << "Invalid error: \"" << error.asString() << "\"" << endl; abort(); } } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index bb274614..3b137572 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2950,6 +2950,19 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) CHECK_ERROR(text, TypeError, ""); } +BOOST_AUTO_TEST_CASE(tuple_assignment_from_void_function) +{ + char const* text = R"( + contract C { + function f() { } + function g() { + var (x,) = (f(), f()); + } + } + )"; + CHECK_ERROR(text, TypeError, "Cannot declare variable with void (empty tuple) type."); +} + BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) { char const* text = R"( @@ -4736,6 +4749,23 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) CHECK_ERROR(text, TypeError, ""); } +BOOST_AUTO_TEST_CASE(external_function_to_function_type_calldata_parameter) +{ + // This is a test that checks that the type of the `bytes` parameter is + // correctly changed from its own type `bytes calldata` to `bytes memory` + // when converting to a function type. + char const* text = R"( + contract C { + function f(function(bytes memory x) external g) { } + function callback(bytes x) external {} + function g() { + f(this.callback); + } + } + )"; + CHECK_SUCCESS(text); +} + BOOST_AUTO_TEST_CASE(external_function_type_to_address) { char const* text = R"( |