aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/control-structures.rst63
-rw-r--r--docs/style-guide.rst2
-rw-r--r--docs/units-and-global-variables.rst5
-rw-r--r--libevmasm/Instruction.cpp4
-rw-r--r--liblll/Parser.cpp4
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp2
-rw-r--r--solc/CommandLineInterface.cpp9
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp20
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()
}