aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-02-28 00:06:10 +0800
committerGitHub <noreply@github.com>2018-02-28 00:06:10 +0800
commit908b46e9a7f56a06c76db9e702fb9b25d8b0d344 (patch)
tree47594aa2e1c58a14557263f04199f01421622106 /test/libsolidity
parent6d8dee586c592b3ed34143b0e4c6cba3b704fa84 (diff)
parentd64aa0eaad50741896020d31c0c93b64c3f03bc1 (diff)
downloaddexon-solidity-908b46e9a7f56a06c76db9e702fb9b25d8b0d344.tar.gz
dexon-solidity-908b46e9a7f56a06c76db9e702fb9b25d8b0d344.tar.zst
dexon-solidity-908b46e9a7f56a06c76db9e702fb9b25d8b0d344.zip
Merge pull request #3476 from ethereum/scoping
C99/C++ scoping rules
Diffstat (limited to 'test/libsolidity')
-rw-r--r--test/libsolidity/SMTChecker.cpp6
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp48
-rw-r--r--test/libsolidity/SolidityExpressionCompiler.cpp19
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp245
4 files changed, 302 insertions, 16 deletions
diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
index 5088ab94..12b5f439 100644
--- a/test/libsolidity/SMTChecker.cpp
+++ b/test/libsolidity/SMTChecker.cpp
@@ -466,7 +466,8 @@ BOOST_AUTO_TEST_CASE(for_loop)
text = R"(
contract C {
function f(uint x) public pure {
- for (uint y = 2; x < 10; ) {
+ uint y;
+ for (y = 2; x < 10; ) {
y = 3;
}
assert(y == 3);
@@ -477,7 +478,8 @@ BOOST_AUTO_TEST_CASE(for_loop)
text = R"(
contract C {
function f(uint x) public pure {
- for (uint y = 2; x < 10; ) {
+ uint y;
+ for (y = 2; x < 10; ) {
y = 3;
}
assert(y == 2);
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 3882e4ea..c352a2c2 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -284,6 +284,54 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions)
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(u256(2)));
}
+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;
+ {
+ x = 3; // This should still assign to the outer variable
+ uint x;
+ x = 4; // This should assign to the new one
+ }
+ return x;
+ }
+ function g() pure public returns (uint x) {
+ x = 7;
+ {
+ x = 3;
+ uint x;
+ return x; // This returns the new variable, i.e. 0
+ }
+ }
+ function h() pure public returns (uint x, uint a, uint b) {
+ x = 7;
+ {
+ x = 3;
+ a = x; // This should read from the outer
+ uint x = 4;
+ b = x;
+ }
+ }
+ function i() pure public returns (uint x, uint a) {
+ x = 7;
+ {
+ x = 3;
+ uint x = x; // This should read from the outer and assign to the inner
+ a = x;
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(3));
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(0));
+ ABI_CHECK(callContractFunction("h()"), encodeArgs(3, 3, 4));
+ ABI_CHECK(callContractFunction("i()"), encodeArgs(3, 3));
+}
+
BOOST_AUTO_TEST_CASE(recursive_calls)
{
char const* sourceCode = R"(
diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp
index 67747386..e2a0c3cd 100644
--- a/test/libsolidity/SolidityExpressionCompiler.cpp
+++ b/test/libsolidity/SolidityExpressionCompiler.cpp
@@ -322,10 +322,10 @@ BOOST_AUTO_TEST_CASE(arithmetics)
{
char const* sourceCode = R"(
contract test {
- function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
+ function f(uint y) { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
}
)";
- bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
+ bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
bytes expectation({byte(Instruction::PUSH1), 0x1,
byte(Instruction::PUSH1), 0x2,
byte(Instruction::PUSH1), 0x3,
@@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(Instruction::PUSH1), 0x6,
byte(Instruction::PUSH1), 0x7,
byte(Instruction::PUSH1), 0x8,
- byte(Instruction::DUP10),
+ byte(Instruction::DUP9),
byte(Instruction::XOR),
byte(Instruction::AND),
byte(Instruction::OR),
@@ -364,13 +364,13 @@ BOOST_AUTO_TEST_CASE(unary_operators)
{
char const* sourceCode = R"(
contract test {
- function f(int y) { var x = !(~+- y == 2); }
+ function f(int y) { !(~+- y == 2); }
}
)";
- bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
+ bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
bytes expectation({byte(Instruction::PUSH1), 0x2,
- byte(Instruction::DUP3),
+ byte(Instruction::DUP2),
byte(Instruction::PUSH1), 0x0,
byte(Instruction::SUB),
byte(Instruction::NOT),
@@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
{
char const* sourceCode = R"(
contract test {
- function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }
+ function f(uint a) returns (uint x) { x = --a ^ (a-- ^ (++a ^ a++)); }
}
)";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}});
@@ -426,7 +426,10 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
byte(Instruction::POP), // second ++
// Stack here: a x a^(a+2)^(a+2)
byte(Instruction::DUP3), // will change
- byte(Instruction::XOR)});
+ byte(Instruction::XOR),
+ byte(Instruction::SWAP1),
+ byte(Instruction::POP),
+ byte(Instruction::DUP1)});
// Stack here: a x a^(a+2)^(a+2)^a
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index be147e48..419e46a7 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -76,15 +76,236 @@ BOOST_AUTO_TEST_CASE(double_function_declaration)
BOOST_AUTO_TEST_CASE(double_variable_declaration)
{
- char const* text = R"(
+ string text = R"(
contract test {
- function f() public {
+ function f() pure public {
uint256 x;
if (true) { uint256 x; }
}
}
)";
- CHECK_ERROR(text, DeclarationError, "Identifier already declared.");
+ CHECK_ERROR(text, DeclarationError, "Identifier already declared");
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_050)
+{
+ string text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ uint256 x;
+ if (true) { uint256 x; }
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "This declaration shadows an existing declaration.",
+ "Experimental features",
+ "Unused local variable",
+ "Unused local variable"
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope)
+{
+ string text = R"(
+ contract test {
+ function f() pure public {
+ { uint x; }
+ { uint x; }
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Identifier already declared");
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_050)
+{
+ string text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ { uint x; }
+ { uint x; }
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "Experimental features",
+ "Unused local variable",
+ "Unused local variable"
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation)
+{
+ string text = R"(
+ contract test {
+ function f() pure public {
+ { uint x; }
+ uint x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Identifier already declared");
+}
+
+BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation_050)
+{
+ string text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ { uint x; }
+ uint x;
+ }
+ }
+ )";
+ CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{
+ "Experimental features",
+ "Unused local variable",
+ "Unused local variable"
+ }));
+}
+BOOST_AUTO_TEST_CASE(scoping_old)
+{
+ char const* text = R"(
+ contract test {
+ function f() pure public {
+ x = 4;
+ uint256 x = 2;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() public {
+ {
+ uint256 x;
+ }
+ x = 2;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_activation_old)
+{
+ char const* text = R"(
+ contract test {
+ function f() pure public {
+ x = 3;
+ uint x;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_activation)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ x = 3;
+ uint x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_self_use)
+{
+ char const* text = R"(
+ contract test {
+ function f() pure public {
+ uint a = a;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(scoping_self_use_050)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ uint a = a;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++){
+ x = 2;
+ }
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Experimental features");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for2)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++)
+ x = 2;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "Experimental features");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for3)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (uint x = 0; x < 10; x ++){
+ x = 2;
+ }
+ x = 4;
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
+}
+
+BOOST_AUTO_TEST_CASE(scoping_for_decl_in_body)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract test {
+ function f() pure public {
+ for (;; y++){
+ uint y = 3;
+ }
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier");
}
BOOST_AUTO_TEST_CASE(name_shadowing)
@@ -1004,7 +1225,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation)
{
char const* text = R"(
contract B {
- function f() mod1(2, true) mod2("0123456") public { }
+ function f() mod1(2, true) mod2("0123456") pure public { }
modifier mod1(uint a, bool b) { if (b) _; }
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
@@ -1039,11 +1260,23 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
{
char const* text = R"(
contract B {
- function f() mod(x) public { uint x = 7; }
+ function f() mod(x) pure public { uint x = 7; }
modifier mod(uint a) { if (a > 0) _; }
}
)";
- CHECK_SUCCESS(text);
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables050)
+{
+ char const* text = R"(
+ pragma experimental "v0.5.0";
+ contract B {
+ function f() mod(x) pure public { uint x = 7; }
+ modifier mod(uint a) { if (a > 0) _; }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "Undeclared identifier.");
}
BOOST_AUTO_TEST_CASE(function_modifier_double_invocation)