aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--Changelog.md3
-rw-r--r--README.md2
-rw-r--r--docs/contracts.rst48
-rw-r--r--docs/control-structures.rst17
-rw-r--r--docs/index.rst1
-rw-r--r--docs/metadata.rst144
-rw-r--r--docs/miscellaneous.rst144
-rw-r--r--libevmasm/Assembly.cpp32
-rw-r--r--libevmasm/Assembly.h21
-rw-r--r--liblll/Compiler.cpp5
-rw-r--r--libsolidity/analysis/StaticAnalyzer.cpp11
-rw-r--r--libsolidity/analysis/TypeChecker.cpp64
-rw-r--r--libsolidity/codegen/Compiler.h10
-rw-r--r--libsolidity/codegen/CompilerContext.h11
-rw-r--r--libsolidity/interface/AssemblyStack.cpp4
-rw-r--r--libsolidity/interface/CompilerStack.cpp18
-rw-r--r--libsolidity/interface/CompilerStack.h10
-rw-r--r--libsolidity/interface/StandardCompiler.cpp6
-rwxr-xr-xscripts/test_emscripten.sh47
-rw-r--r--solc/CommandLineInterface.cpp34
-rw-r--r--solc/CommandLineInterface.h5
-rwxr-xr-xtest/externalTests.sh5
-rw-r--r--test/libsolidity/AnalysisFramework.cpp6
-rw-r--r--test/libsolidity/AnalysisFramework.h2
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp18
26 files changed, 357 insertions, 312 deletions
diff --git a/.travis.yml b/.travis.yml
index 315d29bf..5d6ce442 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -174,7 +174,6 @@ cache:
ccache: true
directories:
- boost_1_57_0
- - build
- $HOME/.local
install:
diff --git a/Changelog.md b/Changelog.md
index 9ca8db0c..62e4eb09 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,9 @@
Features:
* Optimizer: Add new optimization step to remove unused ``JUMPDEST``s.
+ * Type Checker: Display helpful warning for unused function arguments/return parameters.
+ * Type Checker: Do not show the same error multiple times for events.
+ * Type Checker: Greatly reduce the number of duplicate errors shown for duplicate constructors and functions.
* Type Checker: Warn on using literals as tight packing parameters in ``keccak256``, ``sha3``, ``sha256`` and ``ripemd160``.
* Type Checker: Enforce ``view`` and ``pure``.
diff --git a/README.md b/README.md
index 1fed49fb..cb743729 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# The Solidity Contract-Oriented Programming Language
-[![Join the chat at https://gitter.im/ethereum/solidity](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/solidity?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Join the chat at https://gitter.im/ethereum/solidity](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/solidity?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/ethereum/solidity.svg?branch=develop)](https://travis-ci.org/ethereum/solidity)
## Useful links
To get started you can find an introduction to the language in the [Solidity documentation](https://solidity.readthedocs.org). In the documentation, you can find [code examples](https://solidity.readthedocs.io/en/latest/solidity-by-example.html) as well as [a reference](https://solidity.readthedocs.io/en/latest/solidity-in-depth.html) of the syntax and details on how to write smart contracts.
diff --git a/docs/contracts.rst b/docs/contracts.rst
index a1a44665..3bd6f6a8 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -16,51 +16,23 @@ inaccessible.
Creating Contracts
******************
-Contracts can be created "from outside" or from Solidity contracts.
+Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts.
+
+IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements.
+
+Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/etherem/web3.js>`_.
+As of today it has a method called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_
+to facilitate contract creation.
+
When a contract is created, its constructor (a function with the same
name as the contract) is executed once.
-
A constructor is optional. Only one constructor is allowed, and this means
overloading is not supported.
-From ``web3.js``, i.e. the JavaScript
-API, this is done as follows::
-
- // Need to specify some source including contract name for the data param below
- var source = "contract CONTRACT_NAME { function CONTRACT_NAME(uint a, uint b) {} }";
-
- // The json abi array generated by the compiler
- var abiArray = [
- {
- "inputs":[
- {"name":"x","type":"uint256"},
- {"name":"y","type":"uint256"}
- ],
- "type":"constructor"
- },
- {
- "constant":true,
- "inputs":[],
- "name":"x",
- "outputs":[{"name":"","type":"bytes32"}],
- "type":"function"
- }
- ];
-
- var MyContract_ = web3.eth.contract(source);
- MyContract = web3.eth.contract(MyContract_.CONTRACT_NAME.info.abiDefinition);
- // deploy new contract
- var contractInstance = MyContract.new(
- 10,
- 11,
- {from: myAccount, gas: 1000000}
- );
-
.. index:: constructor;arguments
-Internally, constructor arguments are passed after the code of
-the contract itself, but you do not have to care about this
-if you use ``web3.js``.
+Internally, constructor arguments are passed :ref:`ABI encoded <ABI>` after the code of
+the contract itself, but you do not have to care about this if you use ``web3.js``.
If a contract wants to create another contract, the source code
(and the binary) of the created contract has to be known to the creator.
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 05254903..0497365b 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -206,7 +206,7 @@ Those names will still be present on the stack, but they are inaccessible.
return k;
}
}
-
+
.. index:: ! new, contracts;creating
@@ -237,16 +237,17 @@ creation-dependencies are not possible.
D newD = new D(arg);
}
- function createAndEndowD(uint arg, uint amount) {
+ function createAndEndowD(uint arg, uint amount) payable {
// Send ether along with the creation
D newD = (new D).value(amount)(arg);
}
}
-As seen in the example, it is possible to forward Ether to the creation using the ``.value()`` option,
-but it is not possible to limit the amount of gas. If the creation fails
-(due to out-of-stack, not enough balance or other problems), an exception
-is thrown.
+As seen in the example, it is possible to forward Ether while creating
+an instance of ``D`` using the ``.value()`` option, but it is not possible
+to limit the amount of gas.
+If the creation fails (due to out-of-stack, not enough balance or other problems),
+an exception is thrown.
Order of Evaluation of Expressions
==================================
@@ -382,7 +383,7 @@ Solidity uses state-reverting exceptions to handle errors. Such an exception wil
state in the current call (and all its sub-calls) and also flag an error to the caller.
The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception
if the condition is not met. The ``assert`` function should only be used to test for internal errors, and to check invariants.
-The ``require`` function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts.
+The ``require`` function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts.
If used properly, analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing ``assert``. Properly functioning code should never reach a failing assert statement; if this happens there is a bug in your contract which you should fix.
There are two other ways to trigger exceptions: The ``revert`` function can be used to flag an error and
@@ -392,7 +393,7 @@ in a call to ``revert``. The ``throw`` keyword can also be used as an alternativ
.. note::
From version 0.4.13 the ``throw`` keyword is deprecated and will be phased out in the future.
-When exceptions happen in a sub-call, they "bubble up" (i.e. exceptions are rethrown) automatically. Exceptions to this rule are ``send``
+When exceptions happen in a sub-call, they "bubble up" (i.e. exceptions are rethrown) automatically. Exceptions to this rule are ``send``
and the low-level functions ``call``, ``delegatecall`` and ``callcode`` -- those return ``false`` in case
of an exception instead of "bubbling up".
diff --git a/docs/index.rst b/docs/index.rst
index 8c33fb9d..cb093bd6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -144,6 +144,7 @@ Contents
solidity-in-depth.rst
security-considerations.rst
using-the-compiler.rst
+ metadata.rst
abi-spec.rst
style-guide.rst
common-patterns.rst
diff --git a/docs/metadata.rst b/docs/metadata.rst
new file mode 100644
index 00000000..dbde87e8
--- /dev/null
+++ b/docs/metadata.rst
@@ -0,0 +1,144 @@
+#################
+Contract Metadata
+#################
+
+.. index:: metadata, contract verification
+
+The Solidity compiler automatically generates a JSON file, the
+contract metadata, that contains information about the current contract.
+It can be used to query the compiler version, the sources used, the ABI
+and NatSpec documentation in order to more safely interact with the contract
+and to verify its source code.
+
+The compiler appends a Swarm hash of the metadata file to the end of the
+bytecode (for details, see below) of each contract, so that you can retrieve
+the file in an authenticated way without having to resort to a centralized
+data provider.
+
+Of course, you have to publish the metadata file to Swarm (or some other service)
+so that others can access it. The file can be output by using ``solc --metadata``
+and the file will be called ``ContractName_meta.json``.
+It will contain Swarm references to the source code, so you have to upload
+all source files and the metadata file.
+
+The metadata file has the following format. The example below is presented in a
+human-readable way. Properly formatted metadata should use quotes correctly,
+reduce whitespace to a minimum and sort the keys of all objects to arrive at a
+unique formatting.
+Comments are of course also not permitted and used here only for explanatory purposes.
+
+.. code-block:: none
+
+ {
+ // Required: The version of the metadata format
+ version: "1",
+ // Required: Source code language, basically selects a "sub-version"
+ // of the specification
+ language: "Solidity",
+ // Required: Details about the compiler, contents are specific
+ // to the language.
+ compiler: {
+ // Required for Solidity: Version of the compiler
+ version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
+ // Optional: Hash of the compiler binary which produced this output
+ keccak256: "0x123..."
+ },
+ // Required: Compilation source files/source units, keys are file names
+ sources:
+ {
+ "myFile.sol": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x123...",
+ // Required (unless "content" is used, see below): Sorted URL(s)
+ // to the source file, protocol is more or less arbitrary, but a
+ // Swarm URL is recommended
+ "urls": [ "bzzr://56ab..." ]
+ },
+ "mortal": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x234...",
+ // Required (unless "url" is used): literal contents of the source file
+ "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
+ }
+ },
+ // Required: Compiler settings
+ settings:
+ {
+ // Required for Solidity: Sorted list of remappings
+ remappings: [ ":g/dir" ],
+ // Optional: Optimizer settings (enabled defaults to false)
+ optimizer: {
+ enabled: true,
+ runs: 500
+ },
+ // Required for Solidity: File and name of the contract or library this
+ // metadata is created for.
+ compilationTarget: {
+ "myFile.sol": "MyContract"
+ },
+ // Required for Solidity: Addresses for libraries used
+ libraries: {
+ "MyLib": "0x123123..."
+ }
+ },
+ // Required: Generated information about the contract.
+ output:
+ {
+ // Required: ABI definition of the contract
+ abi: [ ... ],
+ // Required: NatSpec user documentation of the contract
+ userdoc: [ ... ],
+ // Required: NatSpec developer documentation of the contract
+ devdoc: [ ... ],
+ }
+ }
+
+.. note::
+ Note the ABI definition above has no fixed order. It can change with compiler versions.
+
+.. note::
+ Since the bytecode of the resulting contract contains the metadata hash, any change to
+ the metadata will result in a change of the bytecode. Furthermore, since the metadata
+ includes a hash of all the sources used, a single whitespace change in any of the source
+ codes will result in a different metadata, and subsequently a different bytecode.
+
+Encoding of the Metadata Hash in the Bytecode
+=============================================
+
+Because we might support other ways to retrieve the metadata file in the future,
+the mapping ``{"bzzr0": <Swarm hash>}`` is stored
+`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
+encoding is not easy to find, its length is added in a two-byte big-endian
+encoding. The current version of the Solidity compiler thus adds the following
+to the end of the deployed bytecode::
+
+ 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
+
+So in order to retrieve the data, the end of the deployed bytecode can be checked
+to match that pattern and use the Swarm hash to retrieve the file.
+
+Usage for Automatic Interface Generation and NatSpec
+====================================================
+
+The metadata is used in the following way: A component that wants to interact
+with a contract (e.g. Mist) retrieves the code of the contract, from that
+the Swarm hash of a file which is then retrieved.
+That file is JSON-decoded into a structure like above.
+
+The component can then use the ABI to automatically generate a rudimentary
+user interface for the contract.
+
+Furthermore, Mist can use the userdoc to display a confirmation message to the user
+whenever they interact with the contract.
+
+Usage for Source Code Verification
+==================================
+
+In order to verify the compilation, sources can be retrieved from Swarm
+via the link in the metadata file.
+The compiler of the correct version (which is checked to be part of the "official" compilers)
+is invoked on that input with the specified settings. The resulting
+bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
+This automatically verifies the metadata since its hash is part of the bytecode.
+Excess data corresponds to the constructor input data, which should be decoded
+according to the interface and presented to the user.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index e9b01340..6d6c25ac 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -221,150 +221,6 @@ This means the following source mappings represent the same information:
``1:2:1;:9;2::2;;``
-*****************
-Contract Metadata
-*****************
-
-The Solidity compiler automatically generates a JSON file, the
-contract metadata, that contains information about the current contract.
-It can be used to query the compiler version, the sources used, the ABI
-and NatSpec documentation in order to more safely interact with the contract
-and to verify its source code.
-
-The compiler appends a Swarm hash of the metadata file to the end of the
-bytecode (for details, see below) of each contract, so that you can retrieve
-the file in an authenticated way without having to resort to a centralized
-data provider.
-
-Of course, you have to publish the metadata file to Swarm (or some other service)
-so that others can access it. The file can be output by using ``solc --metadata``
-and the file will be called ``ContractName_meta.json``.
-It will contain Swarm references to the source code, so you have to upload
-all source files and the metadata file.
-
-The metadata file has the following format. The example below is presented in a
-human-readable way. Properly formatted metadata should use quotes correctly,
-reduce whitespace to a minimum and sort the keys of all objects to arrive at a
-unique formatting.
-Comments are of course also not permitted and used here only for explanatory purposes.
-
-.. code-block:: none
-
- {
- // Required: The version of the metadata format
- version: "1",
- // Required: Source code language, basically selects a "sub-version"
- // of the specification
- language: "Solidity",
- // Required: Details about the compiler, contents are specific
- // to the language.
- compiler: {
- // Required for Solidity: Version of the compiler
- version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
- // Optional: Hash of the compiler binary which produced this output
- keccak256: "0x123..."
- },
- // Required: Compilation source files/source units, keys are file names
- sources:
- {
- "myFile.sol": {
- // Required: keccak256 hash of the source file
- "keccak256": "0x123...",
- // Required (unless "content" is used, see below): Sorted URL(s)
- // to the source file, protocol is more or less arbitrary, but a
- // Swarm URL is recommended
- "urls": [ "bzzr://56ab..." ]
- },
- "mortal": {
- // Required: keccak256 hash of the source file
- "keccak256": "0x234...",
- // Required (unless "url" is used): literal contents of the source file
- "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
- }
- },
- // Required: Compiler settings
- settings:
- {
- // Required for Solidity: Sorted list of remappings
- remappings: [ ":g/dir" ],
- // Optional: Optimizer settings (enabled defaults to false)
- optimizer: {
- enabled: true,
- runs: 500
- },
- // Required for Solidity: File and name of the contract or library this
- // metadata is created for.
- compilationTarget: {
- "myFile.sol": "MyContract"
- },
- // Required for Solidity: Addresses for libraries used
- libraries: {
- "MyLib": "0x123123..."
- }
- },
- // Required: Generated information about the contract.
- output:
- {
- // Required: ABI definition of the contract
- abi: [ ... ],
- // Required: NatSpec user documentation of the contract
- userdoc: [ ... ],
- // Required: NatSpec developer documentation of the contract
- devdoc: [ ... ],
- }
- }
-
-.. note::
- Note the ABI definition above has no fixed order. It can change with compiler versions.
-
-.. note::
- Since the bytecode of the resulting contract contains the metadata hash, any change to
- the metadata will result in a change of the bytecode. Furthermore, since the metadata
- includes a hash of all the sources used, a single whitespace change in any of the source
- codes will result in a different metadata, and subsequently a different bytecode.
-
-Encoding of the Metadata Hash in the Bytecode
-=============================================
-
-Because we might support other ways to retrieve the metadata file in the future,
-the mapping ``{"bzzr0": <Swarm hash>}`` is stored
-`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
-encoding is not easy to find, its length is added in a two-byte big-endian
-encoding. The current version of the Solidity compiler thus adds the following
-to the end of the deployed bytecode::
-
- 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
-
-So in order to retrieve the data, the end of the deployed bytecode can be checked
-to match that pattern and use the Swarm hash to retrieve the file.
-
-Usage for Automatic Interface Generation and NatSpec
-====================================================
-
-The metadata is used in the following way: A component that wants to interact
-with a contract (e.g. Mist) retrieves the code of the contract, from that
-the Swarm hash of a file which is then retrieved.
-That file is JSON-decoded into a structure like above.
-
-The component can then use the ABI to automatically generate a rudimentary
-user interface for the contract.
-
-Furthermore, Mist can use the userdoc to display a confirmation message to the user
-whenever they interact with the contract.
-
-Usage for Source Code Verification
-==================================
-
-In order to verify the compilation, sources can be retrieved from Swarm
-via the link in the metadata file.
-The compiler of the correct version (which is checked to be part of the "official" compilers)
-is invoked on that input with the specified settings. The resulting
-bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
-This automatically verifies the metadata since its hash is part of the bytecode.
-Excess data corresponds to the constructor input data, which should be decoded
-according to the interface and presented to the user.
-
-
***************
Tips and Tricks
***************
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 8c1f9296..6b4bb52b 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -181,7 +181,7 @@ private:
}
-ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
+void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const
{
Functionalizer f(_out, _prefix, _sourceCodes);
@@ -199,18 +199,23 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
for (size_t i = 0; i < m_subs.size(); ++i)
{
_out << endl << _prefix << "sub_" << i << ": assembly {\n";
- m_subs[i]->streamAsm(_out, _prefix + " ", _sourceCodes);
+ m_subs[i]->assemblyStream(_out, _prefix + " ", _sourceCodes);
_out << _prefix << "}" << endl;
}
}
if (m_auxiliaryData.size() > 0)
_out << endl << _prefix << "auxdata: 0x" << toHex(m_auxiliaryData) << endl;
+}
- return _out;
+string Assembly::assemblyString(StringMap const& _sourceCodes) const
+{
+ ostringstream tmp;
+ assemblyStream(tmp, "", _sourceCodes);
+ return tmp.str();
}
-Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string _value, string _jumpType) const
+Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string _value, string _jumpType)
{
Json::Value value;
value["name"] = _name;
@@ -223,14 +228,14 @@ Json::Value Assembly::createJsonValue(string _name, int _begin, int _end, string
return value;
}
-string toStringInHex(u256 _value)
+string Assembly::toStringInHex(u256 _value)
{
std::stringstream hexStr;
hexStr << hex << _value;
return hexStr.str();
}
-Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes) const
+Json::Value Assembly::assemblyJSON(StringMap const& _sourceCodes) const
{
Json::Value root;
@@ -301,29 +306,16 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
{
std::stringstream hexStr;
hexStr << hex << i;
- data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
+ data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceCodes);
}
}
if (m_auxiliaryData.size() > 0)
root[".auxdata"] = toHex(m_auxiliaryData);
- _out << root;
-
return root;
}
-Json::Value Assembly::stream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes, bool _inJsonFormat) const
-{
- if (_inJsonFormat)
- return streamAsmJson(_out, _sourceCodes);
- else
- {
- streamAsm(_out, _prefix, _sourceCodes);
- return Json::Value();
- }
-}
-
AssemblyItem const& Assembly::append(AssemblyItem const& _i)
{
assertThrow(m_deposit >= 0, AssemblyException, "");
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h
index 680cb1af..cbdd71bc 100644
--- a/libevmasm/Assembly.h
+++ b/libevmasm/Assembly.h
@@ -120,11 +120,19 @@ public:
/// If @a _enable is not set, will perform some simple peephole optimizations.
Assembly& optimise(bool _enable, bool _isCreation = true, size_t _runs = 200);
- Json::Value stream(
+ /// Create a text representation of the assembly.
+ std::string assemblyString(
+ StringMap const& _sourceCodes = StringMap()
+ ) const;
+ void assemblyStream(
std::ostream& _out,
std::string const& _prefix = "",
- const StringMap &_sourceCodes = StringMap(),
- bool _inJsonFormat = false
+ StringMap const& _sourceCodes = StringMap()
+ ) const;
+
+ /// Create a JSON representation of the assembly.
+ Json::Value assemblyJSON(
+ StringMap const& _sourceCodes = StringMap()
) const;
protected:
@@ -136,9 +144,8 @@ protected:
unsigned bytesRequired(unsigned subTagSize) const;
private:
- Json::Value streamAsmJson(std::ostream& _out, StringMap const& _sourceCodes) const;
- std::ostream& streamAsm(std::ostream& _out, std::string const& _prefix, StringMap const& _sourceCodes) const;
- Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
+ static Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string());
+ static std::string toStringInHex(u256 _value);
protected:
/// 0 is reserved for exception
@@ -161,7 +168,7 @@ protected:
inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
{
- _a.stream(_out);
+ _a.assemblyStream(_out);
return _out;
}
diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp
index 4ec11ca9..b69675aa 100644
--- a/liblll/Compiler.cpp
+++ b/liblll/Compiler.cpp
@@ -72,14 +72,13 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v
{
CompilerState cs;
cs.populateStandard();
- stringstream ret;
auto assembly = CodeFragment::compile(_src, cs).assembly(cs);
if (_opt)
assembly = assembly.optimise(true);
- assembly.stream(ret);
+ string ret = assembly.assemblyString();
for (auto i: cs.treesToKill)
killBigints(i);
- return ret.str();
+ return ret;
}
catch (Exception const& _e)
{
diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp
index ab1cbb52..ffa538b6 100644
--- a/libsolidity/analysis/StaticAnalyzer.cpp
+++ b/libsolidity/analysis/StaticAnalyzer.cpp
@@ -67,7 +67,16 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
m_constructor = false;
for (auto const& var: m_localVarUseCount)
if (var.second == 0)
- m_errorReporter.warning(var.first->location(), "Unused local variable");
+ {
+ if (var.first->isCallableParameter())
+ m_errorReporter.warning(
+ var.first->location(),
+ "Unused function parameter. Remove or comment out the variable name to silence this warning."
+ );
+ else
+ m_errorReporter.warning(var.first->location(), "Unused local variable.");
+ }
+
m_localVarUseCount.clear();
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 966ca560..26529c22 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -164,28 +164,52 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
for (; it != functions[_contract.name()].end(); ++it)
ssl.append("Another declaration is here:", (*it)->location());
+ string msg = "More than one constructor defined.";
+ size_t occurrences = ssl.infos.size();
+ if (occurrences > 32)
+ {
+ ssl.infos.resize(32);
+ msg += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences.";
+ }
+
m_errorReporter.declarationError(
functions[_contract.name()].front()->location(),
ssl,
- "More than one constructor defined."
+ msg
);
}
for (auto const& it: functions)
{
vector<FunctionDefinition const*> const& overloads = it.second;
- for (size_t i = 0; i < overloads.size(); ++i)
+ set<size_t> reported;
+ for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
+ {
+ SecondarySourceLocation ssl;
+
for (size_t j = i + 1; j < overloads.size(); ++j)
if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j])))
{
- m_errorReporter.declarationError(
- overloads[j]->location(),
- SecondarySourceLocation().append(
- "Other declaration is here:",
- overloads[i]->location()
- ),
- "Function with same name and arguments defined twice."
- );
+ ssl.append("Other declaration is here:", overloads[j]->location());
+ reported.insert(j);
+ }
+
+ if (ssl.infos.size() > 0)
+ {
+ string msg = "Function with same name and arguments defined twice.";
+ size_t occurrences = ssl.infos.size();
+ if (occurrences > 32)
+ {
+ ssl.infos.resize(32);
+ msg += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences.";
}
+
+ m_errorReporter.declarationError(
+ overloads[i]->location(),
+ ssl,
+ msg
+ );
+ }
+ }
}
}
@@ -461,7 +485,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
" to " +
parameterTypes[i]->toString() +
" requested."
- );
+ );
}
void TypeChecker::endVisit(UsingForDirective const& _usingFor)
@@ -701,15 +725,15 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
{
if (var->isIndexed())
numIndexed++;
- if (_eventDef.isAnonymous() && numIndexed > 4)
- m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
- else if (!_eventDef.isAnonymous() && numIndexed > 3)
- m_errorReporter.typeError(_eventDef.location(), "More than 3 indexed arguments for event.");
if (!type(*var)->canLiveOutsideStorage())
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (!type(*var)->interfaceType(false))
m_errorReporter.typeError(var->location(), "Internal type is not allowed as event parameter type.");
}
+ if (_eventDef.isAnonymous() && numIndexed > 4)
+ m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
+ else if (!_eventDef.isAnonymous() && numIndexed > 3)
+ m_errorReporter.typeError(_eventDef.location(), "More than 3 indexed arguments for event.");
return false;
}
@@ -1586,14 +1610,16 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
if (contract->contractKind() == ContractDefinition::ContractKind::Interface)
m_errorReporter.fatalTypeError(_newExpression.location(), "Cannot instantiate an interface.");
if (!contract->annotation().unimplementedFunctions.empty())
+ {
+ SecondarySourceLocation ssl;
+ for (auto function: contract->annotation().unimplementedFunctions)
+ ssl.append("Missing implementation:", function->location());
m_errorReporter.typeError(
_newExpression.location(),
- SecondarySourceLocation().append(
- "Missing implementation:",
- contract->annotation().unimplementedFunctions.front()->location()
- ),
+ ssl,
"Trying to create an instance of an abstract contract."
);
+ }
if (!contract->constructorIsPublic())
m_errorReporter.typeError(_newExpression.location(), "Contract with internal constructor cannot be created directly.");
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index c6ee93fb..06654486 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -60,10 +60,14 @@ public:
/// @returns Only the runtime object (without constructor).
eth::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); }
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFromat shows whether the out should be in Json format
- Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
+ std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
- return m_context.streamAssembly(_stream, _sourceCodes, _inJsonFormat);
+ return m_context.assemblyString(_sourceCodes);
+ }
+ /// @arg _sourceCodes is the map of input files to source code strings
+ Json::Value assemblyJSON(StringMap const& _sourceCodes = StringMap()) const
+ {
+ return m_context.assemblyJSON(_sourceCodes);
}
/// @returns Assembly items of the normal compiler context
eth::AssemblyItems const& assemblyItems() const { return m_context.assembly().items(); }
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 3994b010..5116585e 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -209,10 +209,15 @@ public:
eth::Assembly& nonConstAssembly() { return *m_asm; }
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFormat shows whether the out should be in Json format
- Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
+ std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
- return m_asm->stream(_stream, "", _sourceCodes, _inJsonFormat);
+ return m_asm->assemblyString(_sourceCodes);
+ }
+
+ /// @arg _sourceCodes is the map of input files to source code strings
+ Json::Value assemblyJSON(StringMap const& _sourceCodes = StringMap()) const
+ {
+ return m_asm->assemblyJSON(_sourceCodes);
}
eth::LinkerObject const& assembledObject() const { return m_asm->assemble(); }
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index 23524bb3..504ad92c 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -91,9 +91,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const
eth::Assembly assembly;
assembly::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly);
object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble());
- ostringstream tmp;
- assembly.stream(tmp);
- object.assembly = tmp.str();
+ object.assembly = assembly.assemblyString();
return object;
}
case Machine::EVM15:
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 99ad061c..51544f8a 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -358,16 +358,24 @@ eth::LinkerObject const& CompilerStack::cloneObject(string const& _contractName)
return contract(_contractName).cloneObject;
}
-Json::Value CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes, bool _inJsonFormat) const
+/// FIXME: cache this string
+string CompilerStack::assemblyString(string const& _contractName, StringMap _sourceCodes) const
{
Contract const& currentContract = contract(_contractName);
if (currentContract.compiler)
- return currentContract.compiler->streamAssembly(_outStream, _sourceCodes, _inJsonFormat);
+ return currentContract.compiler->assemblyString(_sourceCodes);
+ else
+ return string();
+}
+
+/// FIXME: cache the JSON
+Json::Value CompilerStack::assemblyJSON(string const& _contractName, StringMap _sourceCodes) const
+{
+ Contract const& currentContract = contract(_contractName);
+ if (currentContract.compiler)
+ return currentContract.compiler->assemblyJSON(_sourceCodes);
else
- {
- _outStream << "Contract not fully implemented" << endl;
return Json::Value();
- }
}
vector<string> CompilerStack::sourceNames() const
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 2756e57d..f1bbae47 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -190,11 +190,15 @@ public:
/// if the contract does not (yet) have bytecode.
std::string const* runtimeSourceMapping(std::string const& _contractName = "") const;
- /// Streams a verbose version of the assembly to @a _outStream.
+ /// @return a verbose text representation of the assembly.
/// @arg _sourceCodes is the map of input files to source code strings
- /// @arg _inJsonFromat shows whether the out should be in Json format
/// Prerequisite: Successful compilation.
- Json::Value streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const;
+ std::string assemblyString(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const;
+
+ /// @returns a JSON representation of the assembly.
+ /// @arg _sourceCodes is the map of input files to source code strings
+ /// Prerequisite: Successful compilation.
+ Json::Value assemblyJSON(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const;
/// @returns a JSON representing the contract ABI.
/// Prerequisite: Successful call to parse or compile.
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index be823743..b4fbbef9 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -400,10 +400,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
// EVM
Json::Value evmData(Json::objectValue);
// @TODO: add ir
- ostringstream tmp;
- m_compilerStack.streamAssembly(tmp, contractName, createSourceList(_input), false);
- evmData["assembly"] = tmp.str();
- evmData["legacyAssembly"] = m_compilerStack.streamAssembly(tmp, contractName, createSourceList(_input), true);
+ evmData["assembly"] = m_compilerStack.assemblyString(contractName, createSourceList(_input));
+ evmData["legacyAssembly"] = m_compilerStack.assemblyJSON(contractName, createSourceList(_input));
evmData["methodIdentifiers"] = m_compilerStack.methodIdentifiers(contractName);
evmData["gasEstimates"] = m_compilerStack.gasEstimates(contractName);
diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh
index f1d44a1f..b01b33bb 100755
--- a/scripts/test_emscripten.sh
+++ b/scripts/test_emscripten.sh
@@ -29,28 +29,29 @@
set -e
REPO_ROOT=$(cd $(dirname "$0")/.. && pwd)
-
-cd $REPO_ROOT/build
-
-echo "Preparing solc-js..."
-rm -rf solc-js
-git clone https://github.com/ethereum/solc-js
-cd solc-js
-npm install
-
-# Replace soljson with current build
-echo "Replacing soljson.js"
-rm -f soljson.js
-# Make a copy because paths might not be absolute
-cp ../solc/soljson.js soljson.js
-
-# Update version (needed for some tests)
-VERSION=$(../../scripts/get_version.sh)
-echo "Updating package.json to version $VERSION"
-npm version $VERSION
-
-echo "Running solc-js tests..."
-npm run test
+SOLJSON="$REPO_ROOT/build/solc/soljson.js"
+
+DIR=$(mktemp -d)
+(
+ echo "Preparing solc-js..."
+ git clone --depth 1 https://github.com/ethereum/solc-js "$DIR"
+ cd "$DIR"
+ npm install
+
+ # Replace soljson with current build
+ echo "Replacing soljson.js"
+ rm -f soljson.js
+ cp "$SOLJSON" soljson.js
+
+ # Update version (needed for some tests)
+ VERSION=$("$REPO_ROOT/scripts/get_version.sh")
+ echo "Updating package.json to version $VERSION"
+ npm version --no-git-tag-version $VERSION
+
+ echo "Running solc-js tests..."
+ npm run test
+)
+rm -rf "$DIR"
echo "Running external tests...."
-"$REPO_ROOT"/test/externalTests.sh "$REPO_ROOT"/build/solc/soljson.js
+"$REPO_ROOT/test/externalTests.sh" "$SOLJSON"
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 315f951e..271511d4 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -112,10 +112,12 @@ static string const g_strSourceList = "sourceList";
static string const g_strSrcMap = "srcmap";
static string const g_strSrcMapRuntime = "srcmap-runtime";
static string const g_strStandardJSON = "standard-json";
+static string const g_strPrettyJson = "pretty-json";
static string const g_strVersion = "version";
static string const g_argAbi = g_strAbi;
static string const g_argAddStandard = g_strAddStandard;
+static string const g_argPrettyJson = g_strPrettyJson;
static string const g_argAllowPaths = g_strAllowPaths;
static string const g_argAsm = g_strAsm;
static string const g_argAsmJson = g_strAsmJson;
@@ -508,6 +510,11 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + pathName));
}
+void CommandLineInterface::createJson(string const& _fileName, string const& _json)
+{
+ createFile(boost::filesystem::basename(_fileName) + string(".json"), _json);
+}
+
bool CommandLineInterface::parseArguments(int _argc, char** _argv)
{
// Declare the supported options.
@@ -541,6 +548,7 @@ Allowed options)",
"Estimated number of contract runs for optimizer tuning."
)
(g_argAddStandard.c_str(), "Add standard contracts.")
+ (g_argPrettyJson.c_str(), "Output JSON in pretty format. Currently it only works with the combined JSON output.")
(
g_argLibraries.c_str(),
po::value<vector<string>>()->value_name("libs"),
@@ -865,10 +873,7 @@ void CommandLineInterface::handleCombinedJSON()
if (requests.count(g_strOpcodes))
contractData[g_strOpcodes] = solidity::disassemble(m_compiler->object(contractName).bytecode);
if (requests.count(g_strAsm))
- {
- ostringstream unused;
- contractData[g_strAsm] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true);
- }
+ contractData[g_strAsm] = m_compiler->assemblyJSON(contractName, m_sourceCodes);
if (requests.count(g_strSrcMap))
{
auto map = m_compiler->sourceMapping(contractName);
@@ -908,7 +913,13 @@ void CommandLineInterface::handleCombinedJSON()
output[g_strSources][sourceCode.first]["AST"] = converter.toJson(m_compiler->ast(sourceCode.first));
}
}
- cout << dev::jsonCompactPrint(output) << endl;
+
+ string json = m_args.count(g_argPrettyJson) ? dev::jsonPrettyPrint(output) : dev::jsonCompactPrint(output);
+
+ if (m_args.count(g_argOutputDir))
+ createJson("combined", json);
+ else
+ cout << json << endl;
}
void CommandLineInterface::handleAst(string const& _argStr)
@@ -1150,16 +1161,19 @@ void CommandLineInterface::outputCompilationResults()
// do we need EVM assembly?
if (m_args.count(g_argAsm) || m_args.count(g_argAsmJson))
{
+ string ret;
+ if (m_args.count(g_argAsmJson))
+ ret = dev::jsonPrettyPrint(m_compiler->assemblyJSON(contract, m_sourceCodes));
+ else
+ ret = m_compiler->assemblyString(contract, m_sourceCodes);
+
if (m_args.count(g_argOutputDir))
{
- stringstream data;
- m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJson));
- createFile(m_compiler->filesystemFriendlyName(contract) + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), data.str());
+ createFile(m_compiler->filesystemFriendlyName(contract) + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), ret);
}
else
{
- cout << "EVM assembly:" << endl;
- m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJson));
+ cout << "EVM assembly:" << endl << ret << endl;
}
}
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index bf9400e4..4768c9d8 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -81,6 +81,11 @@ private:
/// @arg _data to be written
void createFile(std::string const& _fileName, std::string const& _data);
+ /// Create a json file in the given directory
+ /// @arg _fileName the name of the file (the extension will be replaced with .json)
+ /// @arg _json json string to be written
+ void createJson(std::string const& _fileName, std::string const& _json);
+
bool m_error = false; ///< If true, some error occurred.
bool m_onlyAssemble = false;
diff --git a/test/externalTests.sh b/test/externalTests.sh
index 1b74561b..6ff2ebc5 100755
--- a/test/externalTests.sh
+++ b/test/externalTests.sh
@@ -38,10 +38,9 @@ SOLJSON="$1"
DIR=$(mktemp -d)
(
- cd "$DIR"
echo "Running Zeppelin tests..."
- git clone https://github.com/OpenZeppelin/zeppelin-solidity.git
- cd zeppelin-solidity
+ git clone --depth 1 https://github.com/OpenZeppelin/zeppelin-solidity.git "$DIR"
+ cd "$DIR"
npm install
cp "$SOLJSON" ./node_modules/solc/soljson.js
npm run test
diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp
index 71bb4ca7..5f5f6411 100644
--- a/test/libsolidity/AnalysisFramework.cpp
+++ b/test/libsolidity/AnalysisFramework.cpp
@@ -106,12 +106,12 @@ void AnalysisFramework::printErrors()
);
}
-ContractDefinition const* AnalysisFramework::retrieveContract(SourceUnit const& _source, unsigned index)
+ContractDefinition const* AnalysisFramework::retrieveContractByName(SourceUnit const& _source, string const& _name)
{
ContractDefinition* contract = nullptr;
- unsigned counter = 0;
+
for (shared_ptr<ASTNode> const& node: _source.nodes())
- if ((contract = dynamic_cast<ContractDefinition*>(node.get())) && counter == index)
+ if ((contract = dynamic_cast<ContractDefinition*>(node.get())) && contract->name() == _name)
return contract;
return nullptr;
diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h
index 0cdedaea..f73f06c2 100644
--- a/test/libsolidity/AnalysisFramework.h
+++ b/test/libsolidity/AnalysisFramework.h
@@ -59,7 +59,7 @@ protected:
void printErrors();
- ContractDefinition const* retrieveContract(SourceUnit const& _source, unsigned index);
+ ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name);
FunctionTypePointer retrieveFunctionBySignature(
ContractDefinition const& _contract,
std::string const& _signature
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 6886fcd0..04d3d2d3 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -976,7 +976,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
SourceUnit const* source;
ContractDefinition const* contract;
source = parseAndAnalyse(text);
- BOOST_REQUIRE((contract = retrieveContract(*source, 0)) != nullptr);
+ BOOST_REQUIRE((contract = retrieveContractByName(*source, "test")) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(*contract, "foo()");
BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->returnParameterTypes();
@@ -1029,7 +1029,7 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
ContractDefinition const* contract;
SourceUnit const* source = parseAndAnalyse(text);
- BOOST_CHECK((contract = retrieveContract(*source, 0)) != nullptr);
+ BOOST_CHECK((contract = retrieveContractByName(*source, "test")) != nullptr);
FunctionTypePointer function;
function = retrieveFunctionBySignature(*contract, "foo()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
@@ -5816,7 +5816,7 @@ BOOST_AUTO_TEST_CASE(warn_unused_local)
}
}
)";
- CHECK_WARNING(text, "Unused");
+ CHECK_WARNING(text, "Unused local variable.");
}
BOOST_AUTO_TEST_CASE(warn_unused_local_assigned)
@@ -5828,10 +5828,10 @@ BOOST_AUTO_TEST_CASE(warn_unused_local_assigned)
}
}
)";
- CHECK_WARNING(text, "Unused");
+ CHECK_WARNING(text, "Unused local variable.");
}
-BOOST_AUTO_TEST_CASE(warn_unused_param)
+BOOST_AUTO_TEST_CASE(warn_unused_function_parameter)
{
char const* text = R"(
contract C {
@@ -5839,7 +5839,7 @@ BOOST_AUTO_TEST_CASE(warn_unused_param)
}
}
)";
- CHECK_WARNING(text, "Unused");
+ CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning.");
text = R"(
contract C {
function f(uint a) pure {
@@ -5849,7 +5849,7 @@ BOOST_AUTO_TEST_CASE(warn_unused_param)
success(text);
}
-BOOST_AUTO_TEST_CASE(warn_unused_return_param)
+BOOST_AUTO_TEST_CASE(warn_unused_return_parameter)
{
char const* text = R"(
contract C {
@@ -5857,7 +5857,7 @@ BOOST_AUTO_TEST_CASE(warn_unused_return_param)
}
}
)";
- CHECK_WARNING(text, "Unused");
+ CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning.");
text = R"(
contract C {
function f() pure returns (uint a) {
@@ -5865,7 +5865,7 @@ BOOST_AUTO_TEST_CASE(warn_unused_return_param)
}
}
)";
- CHECK_WARNING(text, "Unused");
+ CHECK_WARNING(text, "Unused function parameter. Remove or comment out the variable name to silence this warning.");
text = R"(
contract C {
function f() pure returns (uint) {