diff options
-rw-r--r-- | docs/control-structures.rst | 63 | ||||
-rw-r--r-- | docs/style-guide.rst | 2 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 5 | ||||
-rw-r--r-- | libevmasm/Instruction.cpp | 4 | ||||
-rw-r--r-- | liblll/Parser.cpp | 4 | ||||
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.cpp | 2 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 9 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 20 |
8 files changed, 99 insertions, 10 deletions
diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 9ce746ef..1bb0f71a 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -142,6 +142,63 @@ Assigning *to* a state variable always creates an independent copy. On the other .. index:: ! exception, ! throw +Scoping and Declarations +======================== + +.. index:: ! scoping, ! declarations + +In Solidity, a variable declared anywhere within a function will be in scope for the *entire function*, regardless of where it is declared. +This happens because Solidity inherits its scoping rules from JavaScript. +This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block. +As a result, the following code is illegal and cause the compiler to throw an error, `Identifier already declared`:: + + contract ScopingErrors { + function scoping() { + uint i = 0; + + while (i++ < 1) { + uint same1 = 0; + } + + while (i++ < 2) { + uint same1 = 0;// Illegal, second declaration of same1 + } + } + + function minimalScoping() { + { + uint same2 = 0; + } + + { + uint same2 = 0;// Illegal, second declaration of same2 + } + } + + function forLoopScoping() { + for (uint same3 = 0; same3 < 1; same3++) { + } + + for (uint same3 = 0; same3 < 1; same3++) {// Illegal, second declaration of same3 + } + } + } + +In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value. +As a result, the following code is legal, despite being poorly written:: + + function foo() returns (uint) { + // baz is implicitly initialized as 0 + uint bar = 5; + if (true) { + bar += baz; + } + else { + uint baz = 10;// never executes + } + return bar;// returns 5 + } + Exceptions ========== @@ -208,7 +265,7 @@ idea is that assembly libraries will be used to enhance the language in such way // by using o_code = new bytes(size) o_code := mload(0x40) // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), bnot(0x1f)))) + mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // store length in memory mstore(o_code, size) // actually retrieve the code, this needs assembly @@ -292,7 +349,7 @@ The opcodes `pushi` and `jumpdest` cannot be used directly. +-----------------------+------+---------------------------------------------------------------+ | exp(x, y) | | x to the power of y | +-----------------------+------+---------------------------------------------------------------+ -| bnot(x) | | ~x, every bit of x is negated | +| not(x) | | ~x, every bit of x is negated | +-----------------------+------+---------------------------------------------------------------+ | lt(x, y) | | 1 if x < y, 0 otherwise | +-----------------------+------+---------------------------------------------------------------+ @@ -304,7 +361,7 @@ The opcodes `pushi` and `jumpdest` cannot be used directly. +-----------------------+------+---------------------------------------------------------------+ | eq(x, y) | | 1 if x == y, 0 otherwise | +-----------------------+------+---------------------------------------------------------------+ -| not(x) | | 1 if x == 0, 0 otherwise | +| iszero(x) | | 1 if x == 0, 0 otherwise | +-----------------------+------+---------------------------------------------------------------+ | and(x, y) | | bitwise and of x and y | +-----------------------+------+---------------------------------------------------------------+ diff --git a/docs/style-guide.rst b/docs/style-guide.rst index bc32f891..02f89bb8 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -363,7 +363,7 @@ Yes:: address c, address d, address e, - address f, + address f ) { do_something; } diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index a4239a29..141c4a3c 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -117,9 +117,10 @@ Contract Related ---------------- `this` (current contract's type): - the current contract, explicitly convertible to `address` + the current contract, explicitly convertible to :ref:`address` + `selfdestruct(address)`: - destroy the current contract, sending its funds to the given address + destroy the current contract, sending its funds to the given :ref:`address` Furthermore, all functions of the current contract are callable directly including the current function. diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index d854dfec..2aaa6f1d 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -39,13 +39,13 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions = { "MOD", Instruction::MOD }, { "SMOD", Instruction::SMOD }, { "EXP", Instruction::EXP }, - { "BNOT", Instruction::NOT }, + { "NOT", Instruction::NOT }, { "LT", Instruction::LT }, { "GT", Instruction::GT }, { "SLT", Instruction::SLT }, { "SGT", Instruction::SGT }, { "EQ", Instruction::EQ }, - { "NOT", Instruction::ISZERO }, + { "ISZERO", Instruction::ISZERO }, { "AND", Instruction::AND }, { "OR", Instruction::OR }, { "XOR", Instruction::XOR }, diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index df30f389..aa4a4de2 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -21,6 +21,10 @@ #include "Parser.h" +#if _MSC_VER +#pragma warning(disable:4348) +#endif + #define BOOST_RESULT_OF_USE_DECLTYPE #define BOOST_SPIRIT_USE_PHOENIX_V3 #include <boost/spirit/include/qi.hpp> diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 5e407383..26d38cfe 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -296,7 +296,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) { // order in the lists is from derived to base // list of lists to linearize, the last element is the list of direct bases - list<list<ContractDefinition const*>> input(1, {}); + list<list<ContractDefinition const*>> input(1, list<ContractDefinition const*>{}); for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: _contract.baseContracts()) { UserDefinedTypeName const& baseName = baseSpecifier->name(); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 003ad030..21624b3b 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -22,6 +22,13 @@ */ #include "CommandLineInterface.h" +#ifdef _WIN32 // windows + #include <io.h> + #define isatty _isatty + #define fileno _fileno +#else // unix + #include <unistd.h> +#endif #include <string> #include <iostream> #include <fstream> @@ -478,7 +485,7 @@ Allowed options)", return false; } - if (m_args.count("help")) + if (m_args.count("help") || (isatty(fileno(stdin)) && _argc == 1)) { cout << desc; return false; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a220fe09..8c537346 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6755,6 +6755,26 @@ BOOST_AUTO_TEST_CASE(internal_library_function_return_var_size) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); } +BOOST_AUTO_TEST_CASE(iszero_bnot_correct) +{ + // A long time ago, some opcodes were renamed, which involved the opcodes + // "iszero" and "not". + char const* sourceCode = R"( + contract C { + function f() returns (bool) { + bytes32 x = 1; + assembly { x := not(x) } + if (x != ~bytes32(1)) return false; + assembly { x := iszero(x) } + if (x != bytes32(0)) return false; + return true; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } |