aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-06-19 17:53:22 +0800
committerGitHub <noreply@github.com>2017-06-19 17:53:22 +0800
commit0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf (patch)
tree49cfc2be091c868bdc5865a9d718ea33b1a1269e /test/libsolidity
parente0b9589e5a5b961541aefe783045b93fac347773 (diff)
parentc5339037e9c1d25c95093f905ebe443a38d419f0 (diff)
downloaddexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.gz
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.tar.zst
dexon-solidity-0c75afb2c1b9c8e81295c76aa1caa2a48b239aaf.zip
Merge pull request #2225 from ethereum/julia-for
Implement for statement in assembly parser / printer / code generator
Diffstat (limited to 'test/libsolidity')
-rw-r--r--test/libsolidity/InlineAssembly.cpp48
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp49
2 files changed, 97 insertions, 0 deletions
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index aae6dacd..7b760a1d 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -269,6 +269,7 @@ BOOST_AUTO_TEST_CASE(switch_invalid_expression)
{
CHECK_PARSE_ERROR("{ switch {} default {} }", ParserError, "Literal, identifier or instruction expected.");
CHECK_PARSE_ERROR("{ switch calldatasize default {} }", ParserError, "Instructions are not supported as expressions for switch.");
+ CHECK_PARSE_ERROR("{ switch mstore(1, 1) default {} }", ParserError, "Instruction \"mstore\" not allowed in this context");
}
BOOST_AUTO_TEST_CASE(switch_default_before_case)
@@ -291,6 +292,41 @@ BOOST_AUTO_TEST_CASE(switch_invalid_body)
CHECK_PARSE_ERROR("{ switch 42 case 1 mul case 2 {} default {} }", ParserError, "Expected token LBrace got 'Identifier'");
}
+BOOST_AUTO_TEST_CASE(for_statement)
+{
+ BOOST_CHECK(successParse("{ for {} 1 {} {} }"));
+ BOOST_CHECK(successParse("{ for { let i := 1 } lt(i, 5) { i := add(i, 1) } {} }"));
+}
+
+BOOST_AUTO_TEST_CASE(for_invalid_expression)
+{
+ CHECK_PARSE_ERROR("{ for {} {} {} {} }", ParserError, "Literal, identifier or instruction expected.");
+ CHECK_PARSE_ERROR("{ for 1 1 {} {} }", ParserError, "Expected token LBrace got 'Number'");
+ CHECK_PARSE_ERROR("{ for {} 1 1 {} }", ParserError, "Expected token LBrace got 'Number'");
+ CHECK_PARSE_ERROR("{ for {} 1 {} 1 }", ParserError, "Expected token LBrace got 'Number'");
+ CHECK_PARSE_ERROR("{ for {} calldatasize {} {} }", ParserError, "Instructions are not supported as conditions for the for statement.");
+ CHECK_PARSE_ERROR("{ for {} mstore(1, 1) {} {} }", ParserError, "Instruction \"mstore\" not allowed in this context");
+}
+
+BOOST_AUTO_TEST_CASE(for_visibility)
+{
+ BOOST_CHECK(successParse("{ for { let i := 1 } i { pop(i) } { pop(i) } }"));
+ CHECK_PARSE_ERROR("{ for {} i { let i := 1 } {} }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for {} 1 { let i := 1 } { pop(i) } }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for {} 1 { pop(i) } { let i := 1 } }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for { pop(i) } 1 { let i := 1 } {} }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for { pop(i) } 1 { } { let i := 1 } }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for {} i {} { let i := 1 } }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for {} 1 { pop(i) } { let i := 1 } }", DeclarationError, "Identifier not found");
+ CHECK_PARSE_ERROR("{ for { let x := 1 } 1 { let x := 1 } {} }", DeclarationError, "Variable name x already taken in this scope");
+ CHECK_PARSE_ERROR("{ for { let x := 1 } 1 {} { let x := 1 } }", DeclarationError, "Variable name x already taken in this scope");
+ CHECK_PARSE_ERROR("{ let x := 1 for { let x := 1 } 1 {} {} }", DeclarationError, "Variable name x already taken in this scope");
+ CHECK_PARSE_ERROR("{ let x := 1 for {} 1 { let x := 1 } {} }", DeclarationError, "Variable name x already taken in this scope");
+ CHECK_PARSE_ERROR("{ let x := 1 for {} 1 {} { let x := 1 } }", DeclarationError, "Variable name x already taken in this scope");
+ // Check that body and post are not sub-scopes of each other.
+ BOOST_CHECK(successParse("{ for {} 1 { let x := 1 } { let x := 1 } }"));
+}
+
BOOST_AUTO_TEST_CASE(blocks)
{
BOOST_CHECK(successParse("{ let x := 7 { let y := 3 } { let z := 2 } }"));
@@ -409,6 +445,11 @@ BOOST_AUTO_TEST_CASE(print_switch)
parsePrintCompare("{\n switch 42\n case 1 {\n }\n case 2 {\n }\n default {\n }\n}");
}
+BOOST_AUTO_TEST_CASE(print_for)
+{
+ parsePrintCompare("{\n let ret := 5\n for {\n let i := 1\n }\n lt(i, 15)\n {\n i := add(i, 1)\n }\n {\n ret := mul(ret, i)\n }\n}");
+}
+
BOOST_AUTO_TEST_CASE(function_definitions_multiple_args)
{
parsePrintCompare("{\n function f(a, d)\n {\n mstore(a, d)\n }\n function g(a, d) -> x, y\n {\n }\n}");
@@ -534,6 +575,13 @@ BOOST_AUTO_TEST_CASE(switch_statement)
BOOST_CHECK(successAssemble("{ let a := 2 switch calldataload(0) case 1 { a := 1 } case 2 { a := 5 } }"));
}
+BOOST_AUTO_TEST_CASE(for_statement)
+{
+ BOOST_CHECK(successAssemble("{ for {} 1 {} {} }"));
+ BOOST_CHECK(successAssemble("{ let x := calldatasize() for { let i := 0} lt(i, x) { i := add(i, 1) } { mstore(i, 2) } }"));
+}
+
+
BOOST_AUTO_TEST_CASE(large_constant)
{
auto source = R"({
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 52ce65f1..ba507e0c 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -7685,6 +7685,55 @@ BOOST_AUTO_TEST_CASE(inline_assembly_recursion)
BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24)));
}
+BOOST_AUTO_TEST_CASE(inline_assembly_for)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a) returns (uint b) {
+ assembly {
+ function fac(n) -> nf {
+ nf := 1
+ for { let i := n } gt(i, 0) { i := sub(i, 1) } {
+ nf := mul(nf, i)
+ }
+ }
+ b := fac(a)
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24)));
+}
+
+BOOST_AUTO_TEST_CASE(inline_assembly_for2)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint st;
+ function f(uint a) returns (uint b, uint c, uint d) {
+ st = 0;
+ assembly {
+ function sideeffect(r) -> x { sstore(0, add(sload(0), r)) x := 1}
+ for { let i := a } eq(i, sideeffect(2)) { d := add(d, 3) } {
+ b := i
+ i := 0
+ }
+ }
+ c = st;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0), u256(2), u256(0)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1), u256(4), u256(3)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0), u256(2), u256(0)));
+}
+
BOOST_AUTO_TEST_CASE(index_access_with_type_conversion)
{
// Test for a bug where higher order bits cleanup was not done for array index access.