aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md6
-rw-r--r--cmake/jsoncpp.cmake14
-rw-r--r--docs/contracts.rst1
-rw-r--r--docs/yul.rst2
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp3
-rw-r--r--libsolidity/analysis/TypeChecker.cpp17
-rw-r--r--libsolidity/ast/ExperimentalFeatures.h3
-rw-r--r--libsolidity/ast/Types.cpp23
-rw-r--r--libsolidity/ast/Types.h2
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp12
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/boostTest.cpp15
-rw-r--r--test/compilationTests/milestonetracker/RLP.sol14
-rw-r--r--test/contracts/Wallet.cpp3
-rw-r--r--test/libjulia/Simplifier.cpp10
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp3
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol14
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol7
-rw-r--r--test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol3
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/440_warn_unused_return_parameter_with_explicit_return.sol7
-rw-r--r--test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol14
-rw-r--r--test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol14
-rw-r--r--test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol19
-rw-r--r--test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol19
-rw-r--r--test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol18
-rw-r--r--test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol11
-rw-r--r--test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol10
-rw-r--r--test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol10
-rw-r--r--test/tools/isoltest.cpp35
29 files changed, 205 insertions, 108 deletions
diff --git a/Changelog.md b/Changelog.md
index 0790c0ca..2309edc3 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -8,7 +8,6 @@ How to update your code:
* Explicitly state the storage location for local variables of struct and array types, e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``.
* Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``.
-
Breaking Changes:
* ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding.
* Code Generator: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code!
@@ -46,6 +45,7 @@ Breaking Changes:
* Type Checker: Disallow calling base constructors without parentheses. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size.
* Type Checker: Disallow conversions between unrelated contract types. Explicit conversion via ``address`` can still achieve it.
+ * Type Checker: Disallow empty return statements for functions with one or more return values.
* Type Checker: Disallow empty tuple components. This was partly already the case in the experimental 0.5.0 mode.
* Type Checker: Disallow multi-variable declarations with mismatching number of values. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Disallow specifying base constructor arguments multiple times in the same inheritance hierarchy. This was already the case in the experimental 0.5.0 mode.
@@ -57,7 +57,7 @@ Breaking Changes:
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.
* Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract.
* Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore.
- * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
+ * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
* References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode.
* Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode.
* Syntax Checker: Named return values in function types are an error.
@@ -76,6 +76,7 @@ Compiler Features:
* Type Checker: Show named argument in case of error.
* Tests: Determine transaction status during IPC calls.
* Code Generator: Allocate and free local variables according to their scope.
+ * Removed ``pragma experimental "v0.5.0";``.
Bugfixes:
* Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum.
@@ -90,6 +91,7 @@ Bugfixes:
* Type Checker: Disallow assignments to mappings within tuple assignments as well.
* Type Checker: Allow assignments to local variables of mapping types.
* Type Checker: Consider fixed size arrays when checking for recursive structs.
+ * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake
index e886c609..ea3218ef 100644
--- a/cmake/jsoncpp.cmake
+++ b/cmake/jsoncpp.cmake
@@ -10,8 +10,16 @@ set(prefix "${CMAKE_BINARY_DIR}/deps")
set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(JSONCPP_INCLUDE_DIR "${prefix}/include")
-if(NOT MSVC)
- set(JSONCPP_EXTRA_FLAGS "-std=c++11")
+# TODO: Investigate why this breaks some emscripten builds and
+# check whether this can be removed after updating the emscripten
+# versions used in the CI runs.
+if(EMSCRIPTEN)
+ # Do not include all flags in CMAKE_CXX_FLAGS for emscripten,
+ # but only use -std=c++11. Using all flags causes build failures
+ # at the moment.
+ set(JSONCPP_CXX_FLAGS -std=c++11)
+else()
+ set(JSONCPP_CXX_FLAGS ${CMAKE_CXX_FLAGS})
endif()
set(byproducts "")
@@ -34,7 +42,7 @@ ExternalProject_Add(jsoncpp-project
-DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS}
-DJSONCPP_WITH_TESTS=OFF
-DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF
- -DCMAKE_CXX_FLAGS=${JSONCPP_EXTRA_FLAGS}
+ -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
${byproducts}
)
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 2149167b..561d2f97 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -1158,7 +1158,6 @@ Interfaces are similar to abstract contracts, but they cannot have any functions
- Cannot define constructor.
- Cannot define variables.
- Cannot define structs.
-- Cannot define enums.
Some of these restrictions might be lifted in the future.
diff --git a/docs/yul.rst b/docs/yul.rst
index 87ec0c03..87fd95eb 100644
--- a/docs/yul.rst
+++ b/docs/yul.rst
@@ -108,7 +108,7 @@ Grammar::
'break' | 'continue'
FunctionCall =
Identifier '(' ( Expression ( ',' Expression )* )? ')'
- Identifier = [a-zA-Z_$] [a-zA-Z_0-9]*
+ Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]*
IdentifierList = Identifier ( ',' Identifier)*
TypeName = Identifier | BuiltinTypeName
BuiltinTypeName = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index c5ed079d..c5c429ce 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -295,10 +295,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
{
setScope(contract);
if (!resolveNamesAndTypes(*node, false))
- {
success = false;
- break;
- }
}
if (!success)
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 38331a43..6882a14f 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -498,7 +498,12 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
TupleType const& lhs = dynamic_cast<TupleType const&>(*type(_assignment.leftHandSide()));
TupleType const& rhs = dynamic_cast<TupleType const&>(*type(_assignment.rightHandSide()));
- bool fillRight = !lhs.components().empty() && (!lhs.components().back() || lhs.components().front());
+ if (lhs.components().size() != rhs.components().size())
+ {
+ solAssert(m_errorReporter.hasErrors(), "");
+ return;
+ }
+
size_t storageToStorageCopies = 0;
size_t toStorageCopies = 0;
for (size_t i = 0; i < lhs.components().size(); ++i)
@@ -506,10 +511,8 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
ReferenceType const* ref = dynamic_cast<ReferenceType const*>(lhs.components()[i].get());
if (!ref || !ref->dataStoredIn(DataLocation::Storage) || ref->isPointer())
continue;
- size_t rhsPos = fillRight ? i : rhs.components().size() - (lhs.components().size() - i);
- solAssert(rhsPos < rhs.components().size(), "");
toStorageCopies++;
- if (rhs.components()[rhsPos]->dataStoredIn(DataLocation::Storage))
+ if (rhs.components()[i]->dataStoredIn(DataLocation::Storage))
storageToStorageCopies++;
}
if (storageToStorageCopies >= 1 && toStorageCopies >= 2)
@@ -979,9 +982,13 @@ bool TypeChecker::visit(ForStatement const& _forStatement)
void TypeChecker::endVisit(Return const& _return)
{
+ ParameterList const* params = _return.annotation().functionReturnParameters;
if (!_return.expression())
+ {
+ if (params && !params->parameters().empty())
+ m_errorReporter.typeError(_return.location(), "Return arguments required.");
return;
- ParameterList const* params = _return.annotation().functionReturnParameters;
+ }
if (!params)
{
m_errorReporter.typeError(_return.location(), "Return arguments not allowed.");
diff --git a/libsolidity/ast/ExperimentalFeatures.h b/libsolidity/ast/ExperimentalFeatures.h
index c66a3659..54aad573 100644
--- a/libsolidity/ast/ExperimentalFeatures.h
+++ b/libsolidity/ast/ExperimentalFeatures.h
@@ -31,7 +31,6 @@ enum class ExperimentalFeature
{
ABIEncoderV2, // new ABI encoder that makes use of Yul
SMTChecker,
- V050, // v0.5.0 breaking changes
Test,
TestOnlyAnalysis
};
@@ -40,14 +39,12 @@ static const std::map<ExperimentalFeature, bool> ExperimentalFeatureOnlyAnalysis
{
{ ExperimentalFeature::SMTChecker, true },
{ ExperimentalFeature::TestOnlyAnalysis, true },
- { ExperimentalFeature::V050, true }
};
static const std::map<std::string, ExperimentalFeature> ExperimentalFeatureNames =
{
{ "ABIEncoderV2", ExperimentalFeature::ABIEncoderV2 },
{ "SMTChecker", ExperimentalFeature::SMTChecker },
- { "v0.5.0", ExperimentalFeature::V050 },
{ "__test", ExperimentalFeature::Test },
{ "__testOnlyAnalysis", ExperimentalFeature::TestOnlyAnalysis },
};
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 3eccc6d4..565d197a 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -254,6 +254,17 @@ string Type::escapeIdentifier(string const& _identifier)
return ret;
}
+string Type::identifier() const
+{
+ string ret = escapeIdentifier(richIdentifier());
+ solAssert(ret.find_first_of("0123456789") != 0, "Identifier cannot start with a number.");
+ solAssert(
+ ret.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMONPQRSTUVWXYZ_$") == string::npos,
+ "Identifier contains invalid characters."
+ );
+ return ret;
+}
+
TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
{
solAssert(Token::isElementaryTypeName(_type.token()),
@@ -2293,16 +2304,14 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons
{
solAssert(!!_targetType, "");
TypePointers const& targetComponents = dynamic_cast<TupleType const&>(*_targetType).components();
- bool fillRight = !targetComponents.empty() && (!targetComponents.back() || targetComponents.front());
+ solAssert(components().size() == targetComponents.size(), "");
TypePointers tempComponents(targetComponents.size());
- for (size_t i = 0; i < min(targetComponents.size(), components().size()); ++i)
+ for (size_t i = 0; i < targetComponents.size(); ++i)
{
- size_t si = fillRight ? i : components().size() - i - 1;
- size_t ti = fillRight ? i : targetComponents.size() - i - 1;
- if (components()[si] && targetComponents[ti])
+ if (components()[i] && targetComponents[i])
{
- tempComponents[ti] = components()[si]->closestTemporaryType(targetComponents[ti]);
- solAssert(tempComponents[ti], "");
+ tempComponents[i] = components()[i]->closestTemporaryType(targetComponents[i]);
+ solAssert(tempComponents[i], "");
}
}
return make_shared<TupleType>(tempComponents);
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 09323d05..1fa2b2f5 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -172,7 +172,7 @@ public:
/// only if they have the same identifier.
/// The identifier should start with "t_".
/// Will not contain any character which would be invalid as an identifier.
- std::string identifier() const { return escapeIdentifier(richIdentifier()); }
+ std::string identifier() const;
/// More complex identifier strings use "parentheses", where $_ is interpreted as as
/// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index bd3ec8f5..b30851fb 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -947,20 +947,12 @@ void CompilerUtils::convertType(
{
TupleType const& sourceTuple = dynamic_cast<TupleType const&>(_typeOnStack);
TupleType const& targetTuple = dynamic_cast<TupleType const&>(_targetType);
- // fillRight: remove excess values at right side, !fillRight: remove eccess values at left side
- bool fillRight = !targetTuple.components().empty() && (
- !targetTuple.components().back() ||
- targetTuple.components().front()
- );
+ solAssert(targetTuple.components().size() == sourceTuple.components().size(), "");
unsigned depth = sourceTuple.sizeOnStack();
for (size_t i = 0; i < sourceTuple.components().size(); ++i)
{
TypePointer sourceType = sourceTuple.components()[i];
- TypePointer targetType;
- if (fillRight && i < targetTuple.components().size())
- targetType = targetTuple.components()[i];
- else if (!fillRight && targetTuple.components().size() + i >= sourceTuple.components().size())
- targetType = targetTuple.components()[targetTuple.components().size() - (sourceTuple.components().size() - i)];
+ TypePointer targetType = targetTuple.components()[i];
if (!sourceType)
{
solAssert(!targetType, "");
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 522856cc..701d53e5 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -24,4 +24,8 @@ add_executable(soltest ${sources} ${headers}
)
target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
+if (NOT Boost_USE_STATIC_LIBS)
+ target_compile_definitions(soltest PUBLIC -DBOOST_TEST_DYN_LINK)
+endif()
+
add_subdirectory(tools)
diff --git a/test/boostTest.cpp b/test/boostTest.cpp
index cef3b06f..d9e939eb 100644
--- a/test/boostTest.cpp
+++ b/test/boostTest.cpp
@@ -160,3 +160,18 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] )
return 0;
}
+
+// BOOST_TEST_DYN_LINK should be defined if user want to link against shared boost test library
+#ifdef BOOST_TEST_DYN_LINK
+
+// Because we want to have customized initialization function and support shared boost libraries at the same time,
+// we are forced to customize the entry point.
+// see: https://www.boost.org/doc/libs/1_67_0/libs/test/doc/html/boost_test/adv_scenarios/shared_lib_customizations/init_func.html
+
+int main(int argc, char* argv[])
+{
+ auto init_unit_test = []() -> bool { init_unit_test_suite(0, nullptr); return true; };
+ return boost::unit_test::unit_test_main(init_unit_test, argc, argv);
+}
+
+#endif
diff --git a/test/compilationTests/milestonetracker/RLP.sol b/test/compilationTests/milestonetracker/RLP.sol
index e1f44457..75e3902e 100644
--- a/test/compilationTests/milestonetracker/RLP.sol
+++ b/test/compilationTests/milestonetracker/RLP.sol
@@ -46,7 +46,6 @@ library RLP {
subItem = next(self);
if(strict && !_validate(subItem))
revert();
- return;
}
function hasNext(Iterator memory self) internal view returns (bool) {
@@ -171,10 +170,11 @@ library RLP {
/// @return The bytes.
function toBytes(RLPItem memory self) internal returns (bytes memory bts) {
uint len = self._unsafe_length;
- if (len == 0)
- return;
- bts = new bytes(len);
- _copyToBytes(self._unsafe_memPtr, bts, len);
+ if (len != 0)
+ {
+ bts = new bytes(len);
+ _copyToBytes(self._unsafe_memPtr, bts, len);
+ }
}
/// @dev Decode an RLPItem into bytes. This will not work if the
@@ -359,9 +359,8 @@ library RLP {
if (b0 < DATA_SHORT_START) {
memPtr = start;
len = 1;
- return;
}
- if (b0 < DATA_LONG_START) {
+ else if (b0 < DATA_LONG_START) {
len = self._unsafe_length - 1;
memPtr = start + 1;
} else {
@@ -372,7 +371,6 @@ library RLP {
len = self._unsafe_length - 1 - bLen;
memPtr = start + bLen + 1;
}
- return;
}
// Assumes that enough memory has been allocated to store in target.
diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp
index dc949063..ce50fe59 100644
--- a/test/contracts/Wallet.cpp
+++ b/test/contracts/Wallet.cpp
@@ -199,7 +199,7 @@ contract multiowned {
// determine what index the present sender is:
uint ownerIndex = m_ownerIndex[uint(msg.sender)];
// make sure they're an owner
- if (ownerIndex == 0) return;
+ if (ownerIndex == 0) return false;
PendingState storage pending = m_pending[_operation];
// if we're not yet working on this operation, switch over and reset the confirmation status.
@@ -228,6 +228,7 @@ contract multiowned {
// not enough: record that this owner in particular confirmed.
pending.yetNeeded--;
pending.ownersDone |= ownerIndexBit;
+ return false;
}
}
}
diff --git a/test/libjulia/Simplifier.cpp b/test/libjulia/Simplifier.cpp
index 8ed8287a..e5b7e0d8 100644
--- a/test/libjulia/Simplifier.cpp
+++ b/test/libjulia/Simplifier.cpp
@@ -139,4 +139,14 @@ BOOST_AUTO_TEST_CASE(mod_and)
);
}
+BOOST_AUTO_TEST_CASE(not_applied)
+{
+ CHECK(
+ // The first argument of div is not constant.
+ // keccak256 is not movable.
+ "{ let a := div(keccak256(0, 0), 0) }",
+ "{ let a := div(keccak256(0, 0), 0) }"
+ );
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index a6c1372b..9f7602d1 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -334,10 +334,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions)
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2)));
}
-BOOST_AUTO_TEST_CASE(C99_scoping_activation)
+BOOST_AUTO_TEST_CASE(c99_scoping_activation)
{
char const* sourceCode = R"(
- pragma experimental "v0.5.0";
contract test {
function f() pure public returns (uint) {
uint x = 7;
diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol
deleted file mode 100644
index 0d266ccf..00000000
--- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol
+++ /dev/null
@@ -1,14 +0,0 @@
-contract C {
- struct S { bool f; }
- S s;
- function f() internal pure returns (S storage) { return; }
- function g() internal view returns (S storage c, S storage) { c = s; return; }
- function h() internal view returns (S storage, S storage d) { d = s; return; }
- function i() internal pure returns (S storage, S storage) { return; }
-}
-// ----
-// TypeError: (87-88): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
-// TypeError: (163-164): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
-// TypeError: (233-234): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
-// TypeError: (316-317): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
-// TypeError: (327-328): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol
deleted file mode 100644
index 6d72e4ef..00000000
--- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract C {
- struct S { bool f; }
- S s;
- function f() internal view returns (S storage c, S storage d) { c = s; d = s; return; }
- function g() internal view returns (S storage, S storage) { return (s,s); }
-}
-// ----
diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol
index 0b171560..7567f694 100644
--- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol
+++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_fine.sol
@@ -8,5 +8,8 @@ contract C {
uint a;
(c, a) = f();
}
+ function h() internal view returns (S storage, S storage) {
+ return (s,s);
+ }
}
// ----
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/440_warn_unused_return_parameter_with_explicit_return.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/440_warn_unused_return_parameter_with_explicit_return.sol
deleted file mode 100644
index af67f491..00000000
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/440_warn_unused_return_parameter_with_explicit_return.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract C {
- function f() pure public returns (uint a) {
- return;
- }
-}
-// ----
-// Warning: (51-57): Unused function parameter. Remove or comment out the variable name to silence this warning.
diff --git a/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol
new file mode 100644
index 00000000..9741fdfb
--- /dev/null
+++ b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number.sol
@@ -0,0 +1,14 @@
+contract C
+{
+ function f() public pure returns (uint)
+ {
+ return;
+ }
+ function g() public pure returns (uint)
+ {
+ return (1, 2);
+ }
+}
+// ----
+// TypeError: (71-78): Return arguments required.
+// TypeError: (143-156): Different number of arguments in return statement than in returns declaration.
diff --git a/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol
new file mode 100644
index 00000000..53f2d994
--- /dev/null
+++ b/test/libsolidity/syntaxTests/returnExpressions/single_return_mismatching_number_named.sol
@@ -0,0 +1,14 @@
+contract C
+{
+ function f() public pure returns (uint a)
+ {
+ return;
+ }
+ function g() public pure returns (uint a)
+ {
+ return (1, 2);
+ }
+}
+// ----
+// TypeError: (73-80): Return arguments required.
+// TypeError: (147-160): Different number of arguments in return statement than in returns declaration.
diff --git a/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol
new file mode 100644
index 00000000..4ea61c68
--- /dev/null
+++ b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number.sol
@@ -0,0 +1,19 @@
+contract C
+{
+ function f() public pure returns (uint, uint)
+ {
+ return 1;
+ }
+ function g() public pure returns (uint, uint)
+ {
+ return (1, 2, 3);
+ }
+ function h() public pure returns (uint, uint)
+ {
+ return;
+ }
+}
+// ----
+// TypeError: (77-85): Different number of arguments in return statement than in returns declaration.
+// TypeError: (157-173): Different number of arguments in return statement than in returns declaration.
+// TypeError: (245-252): Return arguments required.
diff --git a/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol
new file mode 100644
index 00000000..86049719
--- /dev/null
+++ b/test/libsolidity/syntaxTests/returnExpressions/tuple_return_mismatching_number_named.sol
@@ -0,0 +1,19 @@
+contract C
+{
+ function f() public pure returns (uint a, uint b)
+ {
+ return 1;
+ }
+ function g() public pure returns (uint a, uint b)
+ {
+ return (1, 2, 3);
+ }
+ function h() public pure returns (uint a, uint b)
+ {
+ return;
+ }
+}
+// ----
+// TypeError: (81-89): Different number of arguments in return statement than in returns declaration.
+// TypeError: (165-181): Different number of arguments in return statement than in returns declaration.
+// TypeError: (257-264): Return arguments required.
diff --git a/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol b/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol
new file mode 100644
index 00000000..e30f9173
--- /dev/null
+++ b/test/libsolidity/syntaxTests/returnExpressions/valid_returns.sol
@@ -0,0 +1,18 @@
+contract C
+{
+ function f() public pure {
+ return;
+ }
+ function g() public pure returns (uint) {
+ return 1;
+ }
+ function h() public pure returns (uint a) {
+ return 1;
+ }
+ function i() public pure returns (uint, uint) {
+ return (1, 2);
+ }
+ function j() public pure returns (uint a, uint b) {
+ return (1, 2);
+ }
+}
diff --git a/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol
new file mode 100644
index 00000000..3cff3a9a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol
@@ -0,0 +1,11 @@
+// This used to crash in certain compiler versions.
+contract CrashContract {
+ struct S { uint a; }
+ S x;
+ function f() public {
+ (x, x) = 1(x, x);
+ }
+}
+// ----
+// TypeError: (170-177): Type is not callable
+// TypeError: (170-177): Type tuple() is not implicitly convertible to expected type tuple(struct CrashContract.S storage ref,struct CrashContract.S storage ref).
diff --git a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol b/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol
deleted file mode 100644
index 902d8b98..00000000
--- a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol
+++ /dev/null
@@ -1,10 +0,0 @@
-contract C {
- struct S { uint a; uint b; }
- S x; S y;
- function f() public {
- (,x, y) = (1, 2, y, x);
- }
-}
-// ----
-// TypeError: (89-101): Type tuple(int_const 1,int_const 2,struct C.S storage ref,struct C.S storage ref) is not implicitly convertible to expected type tuple(,struct C.S storage ref,struct C.S storage ref).
-// Warning: (79-101): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first.
diff --git a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol b/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol
deleted file mode 100644
index 51556aab..00000000
--- a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol
+++ /dev/null
@@ -1,10 +0,0 @@
-contract C {
- struct S { uint a; uint b; }
- S x; S y;
- function f() public {
- (x, y, ) = (y, x, 1, 2);
- }
-}
-// ----
-// TypeError: (90-102): Type tuple(struct C.S storage ref,struct C.S storage ref,int_const 1,int_const 2) is not implicitly convertible to expected type tuple(struct C.S storage ref,struct C.S storage ref,).
-// Warning: (79-102): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first.
diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp
index 7d15b07a..ad6b456d 100644
--- a/test/tools/isoltest.cpp
+++ b/test/tools/isoltest.cpp
@@ -45,8 +45,8 @@ namespace fs = boost::filesystem;
struct TestStats
{
int successCount;
- int runCount;
- operator bool() const { return successCount == runCount; }
+ int testCount;
+ operator bool() const { return successCount == testCount; }
};
class TestTool
@@ -88,13 +88,15 @@ private:
Request handleResponse(bool const _exception);
TestCase::TestCaseCreator m_testCaseCreator;
- bool const m_formatted;
+ bool const m_formatted = false;
string const m_name;
fs::path const m_path;
unique_ptr<TestCase> m_test;
+ static bool m_exitRequested;
};
string TestTool::editor;
+bool TestTool::m_exitRequested = false;
TestTool::Result TestTool::process()
{
@@ -195,7 +197,7 @@ TestStats TestTool::processPath(
std::queue<fs::path> paths;
paths.push(_path);
int successCount = 0;
- int runCount = 0;
+ int testCount = 0;
while (!paths.empty())
{
@@ -212,10 +214,15 @@ TestStats TestTool::processPath(
if (fs::is_directory(entry.path()) || TestCase::isTestFilename(entry.path().filename()))
paths.push(currentPath / entry.path().filename());
}
+ else if (m_exitRequested)
+ {
+ ++testCount;
+ paths.pop();
+ }
else
{
+ ++testCount;
TestTool testTool(_testCaseCreator, currentPath.string(), fullpath, _formatted);
- ++runCount;
auto result = testTool.process();
switch(result)
@@ -225,10 +232,12 @@ TestStats TestTool::processPath(
switch(testTool.handleResponse(result == Result::Exception))
{
case Request::Quit:
- return { successCount, runCount };
+ paths.pop();
+ m_exitRequested = true;
+ break;
case Request::Rerun:
cout << "Re-running test case..." << endl;
- --runCount;
+ --testCount;
break;
case Request::Skip:
paths.pop();
@@ -243,7 +252,7 @@ TestStats TestTool::processPath(
}
}
- return { successCount, runCount };
+ return { successCount, testCount };
}
@@ -347,10 +356,10 @@ Allowed options)",
cout << endl << "Syntax Test Summary: ";
FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) <<
- stats.successCount << "/" << stats.runCount;
+ stats.successCount << "/" << stats.testCount;
cout << " tests successful." << endl << endl;
- global_stats.runCount += stats.runCount;
+ global_stats.testCount += stats.testCount;
global_stats.successCount += stats.successCount;
}
else
@@ -367,10 +376,10 @@ Allowed options)",
cout << endl << "JSON AST Test Summary: ";
FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) <<
- stats.successCount << "/" << stats.runCount;
+ stats.successCount << "/" << stats.testCount;
cout << " tests successful." << endl << endl;
- global_stats.runCount += stats.runCount;
+ global_stats.testCount += stats.testCount;
global_stats.successCount += stats.successCount;
}
else
@@ -381,7 +390,7 @@ Allowed options)",
cout << endl << "Summary: ";
FormattedScope(cout, formatted, {BOLD, global_stats ? GREEN : RED}) <<
- global_stats.successCount << "/" << global_stats.runCount;
+ global_stats.successCount << "/" << global_stats.testCount;
cout << " tests successful." << endl;