aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md2
-rw-r--r--libdevcore/Exceptions.h3
-rw-r--r--libsolidity/analysis/TypeChecker.cpp5
-rw-r--r--libsolidity/ast/Types.cpp2
-rw-r--r--libsolidity/interface/Exceptions.cpp14
-rwxr-xr-xscripts/uniqueErrors.sh14
-rw-r--r--solc/jsonCompiler.cpp6
-rw-r--r--test/fuzzer.cpp3
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp30
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"(