aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md5
-rw-r--r--docs/assembly.rst13
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp5
-rw-r--r--libsolidity/analysis/TypeChecker.cpp8
-rw-r--r--libsolidity/ast/Types.cpp9
-rw-r--r--libsolidity/codegen/Compiler.cpp13
-rw-r--r--libsolidity/codegen/Compiler.h6
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp44
-rw-r--r--libsolidity/codegen/ContractCompiler.h10
-rw-r--r--libsolidity/interface/CompilerStack.cpp23
-rw-r--r--libsolidity/interface/CompilerStack.h7
-rw-r--r--solc/CommandLineInterface.cpp23
-rwxr-xr-xtest/cmdlineTests.sh2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp36
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp51
-rw-r--r--test/libsolidity/SolidityTypes.cpp3
-rw-r--r--test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol9
-rw-r--r--test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol9
-rw-r--r--test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol9
19 files changed, 132 insertions, 153 deletions
diff --git a/Changelog.md b/Changelog.md
index aa2dce18..dbb44983 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -34,6 +34,7 @@ Breaking Changes:
* General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode.
* General: Disallow combining hex numbers with unit denominations (e.g. ``0x1e wei``). This was already the case in the experimental 0.5.0 mode.
* JSON AST: Remove ``constant`` and ``payable`` fields (the information is encoded in the ``stateMutability`` field).
+ * Interface: Remove "clone contract" feature. The ``--clone-bin`` and ``--combined-json clone-bin`` commandline options are not available anymore.
* Name Resolver: Do not exclude public state variables when looking for conflicting declarations.
* Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence.
* Parser: Disallow trailing dots that are not followed by a number.
@@ -78,8 +79,12 @@ Compiler Features:
Bugfixes:
* Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum.
* Code Generator: Fix allocation of byte arrays (zeroed out too much memory).
+ * Code Generator: Properly handle negative number literals in ABIEncoderV2.
+ * Commandline Interface: Correctly handle paths with backslashes on windows.
* Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions.
+ * References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own.
* References Resolver: Enforce ``storage`` as data location for mappings.
+ * References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``.
* References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter.
* Type Checker: Disallow assignments to mappings within tuple assignments as well.
* Type Checker: Allow assignments to local variables of mapping types.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 5041e72c..91ba076a 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -609,12 +609,21 @@ first.
Solidity manages memory in a very simple way: There is a "free memory pointer"
at position ``0x40`` in memory. If you want to allocate memory, just use the memory
-from that point on and update the pointer accordingly.
+starting from where this pointer points at and update it accordingly.
+There is no built-in mechanism to release or free allocated memory.
+Here is an assembly snippet that can be used for allocating memory::
+
+ function allocate(length) -> pos {
+ pos := mload(0x40)
+ mstore(0x40, add(pos, length))
+ }
The first 64 bytes of memory can be used as "scratch space" for short-term
allocation. The 32 bytes after the free memory pointer (i.e. starting at ``0x60``)
is meant to be zero permanently and is used as the initial value for
empty dynamic memory arrays.
+This means that the allocatable memory starts at ``0x80``, which is the initial value
+of the free memory pointer.
Elements in memory arrays in Solidity always occupy multiples of 32 bytes (yes, this is
even true for ``byte[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory
@@ -698,7 +707,7 @@ We consider the runtime bytecode of the following Solidity program::
The following assembly will be generated::
{
- mstore(0x40, 0x60) // store the "free memory pointer"
+ mstore(0x40, 0x80) // store the "free memory pointer"
// function dispatcher
switch div(calldataload(0), exp(2, 226))
case 0xb3de648b {
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index ba793933..5458c1b0 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -256,6 +256,11 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
string("_slot").size() :
string("_offset").size()
));
+ if (realName.empty())
+ {
+ declarationError(_identifier.location, "In variable names _slot and _offset can only be used as a suffix.");
+ return size_t(-1);
+ }
declarations = m_resolver.nameFromCurrentScope(realName);
}
if (declarations.size() != 1)
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 7cec7c43..d98d6af1 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -867,6 +867,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
Declaration const* declaration = ref->second.declaration;
solAssert(!!declaration, "");
+ bool requiresStorage = ref->second.isSlot || ref->second.isOffset;
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
{
if (var->isConstant())
@@ -874,7 +875,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
m_errorReporter.typeError(_identifier.location, "Constant variables not supported by inline assembly.");
return size_t(-1);
}
- else if (ref->second.isSlot || ref->second.isOffset)
+ else if (requiresStorage)
{
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
{
@@ -906,6 +907,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
}
}
+ else if (requiresStorage)
+ {
+ m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
+ return size_t(-1);
+ }
else if (_context == julia::IdentifierContext::LValue)
{
m_errorReporter.typeError(_identifier.location, "Only local variables can be assigned to in inline assembly.");
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 4ee5bfcf..3eccc6d4 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1137,7 +1137,14 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
string RationalNumberType::richIdentifier() const
{
- return "t_rational_" + m_value.numerator().str() + "_by_" + m_value.denominator().str();
+ // rational seemingly will put the sign always on the numerator,
+ // but let just make it deterministic here.
+ bigint numerator = abs(m_value.numerator());
+ bigint denominator = abs(m_value.denominator());
+ if (m_value < 0)
+ return "t_rational_minus_" + numerator.str() + "_by_" + denominator.str();
+ else
+ return "t_rational_" + numerator.str() + "_by_" + denominator.str();
}
bool RationalNumberType::operator==(Type const& _other) const
diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp
index d3afada5..55f1d252 100644
--- a/libsolidity/codegen/Compiler.cpp
+++ b/libsolidity/codegen/Compiler.cpp
@@ -46,19 +46,6 @@ void Compiler::compileContract(
m_context.optimise(m_optimize, m_optimizeRuns);
}
-void Compiler::compileClone(
- ContractDefinition const& _contract,
- map<ContractDefinition const*, eth::Assembly const*> const& _contracts
-)
-{
- solAssert(!_contract.isLibrary(), "");
- ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
- ContractCompiler cloneCompiler(&runtimeCompiler, m_context, m_optimize);
- m_runtimeSub = cloneCompiler.compileClone(_contract, _contracts);
-
- m_context.optimise(m_optimize, m_optimizeRuns);
-}
-
eth::AssemblyItem Compiler::functionEntryLabel(FunctionDefinition const& _function) const
{
return m_runtimeContext.functionEntryLabelIfExists(_function);
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index f6865d75..4028ae63 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -50,12 +50,6 @@ public:
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts,
bytes const& _metadata
);
- /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given
- /// contract at runtime, but contains the full creation-time code.
- void compileClone(
- ContractDefinition const& _contract,
- std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
- );
/// @returns Entire assembly.
eth::Assembly const& assembly() const { return m_context.assembly(); }
/// @returns The entire assembled object (with constructor).
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 2f15a33d..f9493d6d 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -94,27 +94,6 @@ size_t ContractCompiler::compileConstructor(
}
}
-size_t ContractCompiler::compileClone(
- ContractDefinition const& _contract,
- map<ContractDefinition const*, eth::Assembly const*> const& _contracts
-)
-{
- initializeContext(_contract, _contracts);
-
- appendInitAndConstructorCode(_contract);
-
- //@todo determine largest return size of all runtime functions
- auto runtimeSub = m_context.addSubroutine(cloneRuntime());
-
- // stack contains sub size
- m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY;
- m_context << u256(0) << Instruction::RETURN;
-
- appendMissingFunctions();
-
- return size_t(runtimeSub.data());
-}
-
void ContractCompiler::initializeContext(
ContractDefinition const& _contract,
map<ContractDefinition const*, eth::Assembly const*> const& _compiledContracts
@@ -980,29 +959,6 @@ void ContractCompiler::compileExpression(Expression const& _expression, TypePoin
CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType);
}
-eth::AssemblyPointer ContractCompiler::cloneRuntime() const
-{
- eth::Assembly a;
- a << Instruction::CALLDATASIZE;
- a << u256(0) << Instruction::DUP1 << Instruction::CALLDATACOPY;
- //@todo adjust for larger return values, make this dynamic.
- a << u256(0x20) << u256(0) << Instruction::CALLDATASIZE;
- a << u256(0);
- // this is the address which has to be substituted by the linker.
- //@todo implement as special "marker" AssemblyItem.
- a << u256("0xcafecafecafecafecafecafecafecafecafecafe");
- a << u256(eth::GasCosts::callGas(m_context.evmVersion()) + 10) << Instruction::GAS << Instruction::SUB;
- a << Instruction::DELEGATECALL;
- //Propagate error condition (if DELEGATECALL pushes 0 on stack).
- a << Instruction::ISZERO;
- a << Instruction::ISZERO;
- eth::AssemblyItem afterTag = a.appendJumpI().tag();
- a << Instruction::INVALID << afterTag;
- //@todo adjust for larger return values, make this dynamic.
- a << u256(0x20) << u256(0) << Instruction::RETURN;
- return make_shared<eth::Assembly>(a);
-}
-
void ContractCompiler::popScopedVariables(ASTNode const* _node)
{
unsigned blockHeight = m_scopeStackHeight.at(m_modifierDepth).at(_node);
diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h
index 8516ec2c..5fa650b1 100644
--- a/libsolidity/codegen/ContractCompiler.h
+++ b/libsolidity/codegen/ContractCompiler.h
@@ -56,13 +56,6 @@ public:
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
);
- /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given
- /// contract at runtime, but contains the full creation-time code.
- /// @returns the identifier of the runtime sub-assembly.
- size_t compileClone(
- ContractDefinition const& _contract,
- std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
- );
private:
/// Registers the non-function objects inside the contract with the context and stores the basic
@@ -122,9 +115,6 @@ private:
void appendStackVariableInitialisation(VariableDeclaration const& _variable);
void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer());
- /// @returns the runtime assembly for clone contracts.
- eth::AssemblyPointer cloneRuntime() const;
-
/// Frees the variables of a certain scope (to be used when leaving).
void popScopedVariables(ASTNode const* _node);
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 32cb488f..29f9ce7d 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -329,7 +329,6 @@ void CompilerStack::link()
{
contract.second.object.link(m_libraries);
contract.second.runtimeObject.link(m_libraries);
- contract.second.cloneObject.link(m_libraries);
}
}
@@ -408,11 +407,6 @@ eth::LinkerObject const& CompilerStack::runtimeObject(string const& _contractNam
return contract(_contractName).runtimeObject;
}
-eth::LinkerObject const& CompilerStack::cloneObject(string const& _contractName) const
-{
- return contract(_contractName).cloneObject;
-}
-
/// FIXME: cache this string
string CompilerStack::assemblyString(string const& _contractName, StringMap _sourceCodes) const
{
@@ -767,23 +761,6 @@ void CompilerStack::compileContract(
}
_compiledContracts[compiledContract.contract] = &compiler->assembly();
-
- try
- {
- if (!_contract.isLibrary())
- {
- Compiler cloneCompiler(m_evmVersion, m_optimize, m_optimizeRuns);
- cloneCompiler.compileClone(_contract, _compiledContracts);
- compiledContract.cloneObject = cloneCompiler.assembledObject();
- }
- }
- catch (eth::AssemblyException const&)
- {
- // In some cases (if the constructor requests a runtime function), it is not
- // possible to compile the clone.
-
- // TODO: Report error / warning
- }
}
string const CompilerStack::lastContractName() const
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 7b144660..b7d07ca7 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -190,12 +190,6 @@ public:
/// @returns the runtime object for the contract.
eth::LinkerObject const& runtimeObject(std::string const& _contractName) const;
- /// @returns the bytecode of a contract that uses an already deployed contract via DELEGATECALL.
- /// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to
- /// substituted by the actual address. Note that this sequence starts end ends in three X
- /// characters but can contain anything in between.
- eth::LinkerObject const& cloneObject(std::string const& _contractName) const;
-
/// @returns normal contract assembly items
eth::AssemblyItems const* assemblyItems(std::string const& _contractName) const;
@@ -258,7 +252,6 @@ private:
std::shared_ptr<Compiler> compiler;
eth::LinkerObject object; ///< Deployment object (includes the runtime sub-object).
eth::LinkerObject runtimeObject; ///< Runtime object.
- eth::LinkerObject cloneObject; ///< Clone object (deprecated).
std::string metadata; ///< The metadata json that will be hashed into the chain.
mutable std::unique_ptr<Json::Value const> abi;
mutable std::unique_ptr<Json::Value const> userDocumentation;
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 6a768a00..14793759 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -80,7 +80,6 @@ static string const g_strAstJson = "ast-json";
static string const g_strAstCompactJson = "ast-compact-json";
static string const g_strBinary = "bin";
static string const g_strBinaryRuntime = "bin-runtime";
-static string const g_strCloneBinary = "clone-bin";
static string const g_strCombinedJson = "combined-json";
static string const g_strCompactJSON = "compact-format";
static string const g_strContracts = "contracts";
@@ -128,7 +127,6 @@ static string const g_argAstCompactJson = g_strAstCompactJson;
static string const g_argAstJson = g_strAstJson;
static string const g_argBinary = g_strBinary;
static string const g_argBinaryRuntime = g_strBinaryRuntime;
-static string const g_argCloneBinary = g_strCloneBinary;
static string const g_argCombinedJson = g_strCombinedJson;
static string const g_argCompactJSON = g_strCompactJSON;
static string const g_argGas = g_strGas;
@@ -161,7 +159,6 @@ static set<string> const g_combinedJsonArgs
g_strAst,
g_strBinary,
g_strBinaryRuntime,
- g_strCloneBinary,
g_strCompactJSON,
g_strInterface,
g_strMetadata,
@@ -213,7 +210,6 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
g_argAstJson,
g_argBinary,
g_argBinaryRuntime,
- g_argCloneBinary,
g_argMetadata,
g_argNatspecUser,
g_argNatspecDev,
@@ -237,16 +233,6 @@ void CommandLineInterface::handleBinary(string const& _contract)
cout << m_compiler->object(_contract).toHex() << endl;
}
}
- if (m_args.count(g_argCloneBinary))
- {
- if (m_args.count(g_argOutputDir))
- createFile(m_compiler->filesystemFriendlyName(_contract) + ".clone_bin", m_compiler->cloneObject(_contract).toHex());
- else
- {
- cout << "Clone Binary: " << endl;
- cout << m_compiler->cloneObject(_contract).toHex() << endl;
- }
- }
if (m_args.count(g_argBinaryRuntime))
{
if (m_args.count(g_argOutputDir))
@@ -275,7 +261,7 @@ void CommandLineInterface::handleBytecode(string const& _contract)
{
if (m_args.count(g_argOpcodes))
handleOpcode(_contract);
- if (m_args.count(g_argBinary) || m_args.count(g_argCloneBinary) || m_args.count(g_argBinaryRuntime))
+ if (m_args.count(g_argBinary) || m_args.count(g_argBinaryRuntime))
handleBinary(_contract);
}
@@ -438,7 +424,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
continue;
}
- m_sourceCodes[infile.string()] = dev::readFileAsString(infile.string());
+ m_sourceCodes[infile.generic_string()] = dev::readFileAsString(infile.string());
path = boost::filesystem::canonical(infile).string();
}
m_allowedDirectories.push_back(boost::filesystem::path(path).remove_filename());
@@ -631,7 +617,6 @@ Allowed options)",
(g_argOpcodes.c_str(), "Opcodes of the contracts.")
(g_argBinary.c_str(), "Binary of the contracts in hex.")
(g_argBinaryRuntime.c_str(), "Binary of the runtime part of the contracts in hex.")
- (g_argCloneBinary.c_str(), "Binary of the clone contracts in hex.")
(g_argAbi.c_str(), "ABI specification of the contracts.")
(g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.")
(g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.")
@@ -724,7 +709,7 @@ bool CommandLineInterface::processInput()
return ReadCallback::Result{false, "Not a valid file."};
auto contents = dev::readFileAsString(canonicalPath.string());
- m_sourceCodes[path.string()] = contents;
+ m_sourceCodes[path.generic_string()] = contents;
return ReadCallback::Result{true, contents};
}
catch (Exception const& _exception)
@@ -910,8 +895,6 @@ void CommandLineInterface::handleCombinedJSON()
contractData[g_strBinary] = m_compiler->object(contractName).toHex();
if (requests.count(g_strBinaryRuntime))
contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex();
- if (requests.count(g_strCloneBinary))
- contractData[g_strCloneBinary] = m_compiler->cloneObject(contractName).toHex();
if (requests.count(g_strOpcodes))
contractData[g_strOpcodes] = solidity::disassemble(m_compiler->object(contractName).bytecode);
if (requests.count(g_strAsm))
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index bc0ee786..d0296515 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -32,7 +32,7 @@ REPO_ROOT=$(cd $(dirname "$0")/.. && pwd)
echo $REPO_ROOT
SOLC="$REPO_ROOT/build/solc/solc"
-FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc"
+FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtime,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc"
echo "Checking that the bug list is up to date..."
"$REPO_ROOT"/scripts/update_bugs_by_version.py
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 9c287e5e..bd1d9de7 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -12527,6 +12527,42 @@ BOOST_AUTO_TEST_CASE(abi_encode_empty_string_v2)
0x00
));
}
+
+BOOST_AUTO_TEST_CASE(abi_encode_rational)
+{
+ char const* sourceCode = R"(
+ // Tests that rational numbers (even negative ones) are encoded properly.
+ contract C {
+ function f() public pure returns (bytes memory) {
+ return abi.encode(1, -2);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(
+ 0x20,
+ 0x40, u256(1), u256(-2)
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(abi_encode_rational_v2)
+{
+ char const* sourceCode = R"(
+ // Tests that rational numbers (even negative ones) are encoded properly.
+ pragma experimental ABIEncoderV2;
+ contract C {
+ function f() public pure returns (bytes memory) {
+ return abi.encode(1, -2);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(
+ 0x20,
+ 0x40, u256(1), u256(-2)
+ ));
+}
+
BOOST_AUTO_TEST_CASE(abi_encode_call)
{
char const* sourceCode = R"T(
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 98a3bba9..cc44b578 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -41,6 +41,7 @@ public:
void checkNatspec(
std::string const& _code,
+ std::string const& _contractName,
std::string const& _expectedDocumentationString,
bool _userDocumentation
)
@@ -52,9 +53,9 @@ public:
Json::Value generatedDocumentation;
if (_userDocumentation)
- generatedDocumentation = m_compilerStack.natspecUser(m_compilerStack.lastContractName());
+ generatedDocumentation = m_compilerStack.natspecUser(_contractName);
else
- generatedDocumentation = m_compilerStack.natspecDev(m_compilerStack.lastContractName());
+ generatedDocumentation = m_compilerStack.natspecDev(_contractName);
Json::Value expectedDocumentation;
jsonParseStrict(_expectedDocumentationString, expectedDocumentation);
BOOST_CHECK_MESSAGE(
@@ -93,7 +94,7 @@ BOOST_AUTO_TEST_CASE(user_basic_test)
" \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}"
"}}";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
@@ -119,8 +120,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
" \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}"
"}}";
- checkNatspec(sourceCode, devNatspec, false);
- checkNatspec(sourceCode, userNatspec, true);
+ checkNatspec(sourceCode, "test", devNatspec, false);
+ checkNatspec(sourceCode, "test", userNatspec, true);
}
BOOST_AUTO_TEST_CASE(user_multiline_comment)
@@ -140,7 +141,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment)
" \"mul_and_add(uint256,uint256)\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}"
"}}";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(user_multiple_functions)
@@ -171,7 +172,7 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions)
" \"sub(int256)\":{ \"notice\": \"Subtracts 3 from `input`\"}"
"}}";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(user_empty_contract)
@@ -182,7 +183,7 @@ BOOST_AUTO_TEST_CASE(user_empty_contract)
char const* natspec = "{\"methods\":{} }";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(dev_and_user_no_doc)
@@ -201,8 +202,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc)
char const* devNatspec = "{\"methods\":{}}";
char const* userNatspec = "{\"methods\":{}}";
- checkNatspec(sourceCode, devNatspec, false);
- checkNatspec(sourceCode, userNatspec, true);
+ checkNatspec(sourceCode, "test", devNatspec, false);
+ checkNatspec(sourceCode, "test", userNatspec, true);
}
BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
@@ -228,7 +229,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_multiple_params)
@@ -253,7 +254,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace)
@@ -276,7 +277,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
@@ -302,7 +303,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_multiple_functions)
@@ -353,7 +354,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_return)
@@ -381,7 +382,7 @@ BOOST_AUTO_TEST_CASE(dev_return)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
{
@@ -411,7 +412,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
@@ -443,7 +444,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_multiline_comment)
@@ -476,7 +477,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment)
" }\n"
"}}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_contract_no_doc)
@@ -496,7 +497,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc)
" }\n"
"}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_contract_doc)
@@ -520,7 +521,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc)
" }\n"
"}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(dev_author_at_function)
@@ -546,7 +547,7 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function)
" }\n"
"}";
- checkNatspec(sourceCode, natspec, false);
+ checkNatspec(sourceCode, "test", natspec, false);
}
BOOST_AUTO_TEST_CASE(natspec_notice_without_tag)
@@ -569,7 +570,7 @@ BOOST_AUTO_TEST_CASE(natspec_notice_without_tag)
}
)ABCDEF";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag)
@@ -592,7 +593,7 @@ BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag)
}
)ABCDEF";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(empty_comment)
@@ -608,7 +609,7 @@ BOOST_AUTO_TEST_CASE(empty_comment)
}
)ABCDEF";
- checkNatspec(sourceCode, natspec, true);
+ checkNatspec(sourceCode, "test", natspec, true);
}
BOOST_AUTO_TEST_CASE(dev_title_at_function_error)
diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp
index b8b537e5..db0e3b66 100644
--- a/test/libsolidity/SolidityTypes.cpp
+++ b/test/libsolidity/SolidityTypes.cpp
@@ -157,6 +157,9 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
BOOST_CHECK_EQUAL(RationalNumberType(rational(7, 1)).identifier(), "t_rational_7_by_1");
BOOST_CHECK_EQUAL(RationalNumberType(rational(200, 77)).identifier(), "t_rational_200_by_77");
BOOST_CHECK_EQUAL(RationalNumberType(rational(2 * 200, 2 * 77)).identifier(), "t_rational_200_by_77");
+ BOOST_CHECK_EQUAL(RationalNumberType(rational(-2 * 200, -2 * 77)).identifier(), "t_rational_200_by_77");
+ BOOST_CHECK_EQUAL(RationalNumberType(rational(-2 * 200, 2 * 77)).identifier(), "t_rational_minus_200_by_77");
+ BOOST_CHECK_EQUAL(RationalNumberType(rational(2 * 200, -2 * 77)).identifier(), "t_rational_minus_200_by_77");
BOOST_CHECK_EQUAL(
StringLiteralType(Literal(SourceLocation{}, Token::StringLiteral, make_shared<string>("abc - def"))).identifier(),
"t_stringliteral_196a9142ee0d40e274a6482393c762b16dd8315713207365e1e13d8d85b74fc4"
diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol
new file mode 100644
index 00000000..ec23a263
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol
@@ -0,0 +1,9 @@
+contract C {
+ function f() public pure {
+ assembly {
+ _offset
+ }
+ }
+}
+// ----
+// DeclarationError: (75-82): In variable names _slot and _offset can only be used as a suffix.
diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol
new file mode 100644
index 00000000..d493a68a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol
@@ -0,0 +1,9 @@
+contract C {
+ function f() public pure {
+ assembly {
+ _slot
+ }
+ }
+}
+// ----
+// DeclarationError: (75-80): In variable names _slot and _offset can only be used as a suffix.
diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol
new file mode 100644
index 00000000..9165654f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol
@@ -0,0 +1,9 @@
+contract C {
+ function f() pure public {
+ assembly {
+ let x := f_slot
+ }
+ }
+}
+// ----
+// TypeError: (84-90): The suffixes _offset and _slot can only be used on storage variables.