Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth 2020-11-10 13:48:32 +01:00
commit da92fe548e
72 changed files with 608 additions and 112 deletions

View File

@ -18,6 +18,6 @@ indent_size = 4
indent_style = space
indent_size = 4
[*.{txt,cmake}]
[*.{txt,cmake,json}]
indent_style = tab
indent_size = 4

View File

@ -34,6 +34,7 @@ Compiler Features:
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.
* Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
* Standard JSON: New option ``modelCheckerSettings.timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker.
* Assembler: Perform linking in assembly mode when library addresses are provided.
Bugfixes:
@ -45,6 +46,7 @@ Bugfixes:
* SMTChecker: Fix false negative in modifier applied multiple times.
* SMTChecker: Fix internal error in the BMC engine when inherited contract from a different source unit has private state variables.
* SMTChecker: Fix internal error when ``array.push()`` is used as the LHS of an assignment.
* SMTChecker: Fix CHC false positives when branches are used inside modifiers.
* Code generator: Fix missing creation dependency tracking for abstract contracts.

View File

@ -746,7 +746,7 @@ void CHC::clearIndices(ContractDefinition const* _contract, FunctionDefinition c
{
for (auto const& var: _function->parameters() + _function->returnParameters())
m_context.variable(*var)->increaseIndex();
for (auto const& var: _function->localVariables())
for (auto const& var: localVariablesIncludingModifiers(*_function))
m_context.variable(*var)->increaseIndex();
}
@ -821,7 +821,7 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
createVariable(*var);
for (auto var: function->returnParameters())
createVariable(*var);
for (auto const* var: function->localVariables())
for (auto const* var: localVariablesIncludingModifiers(*function))
createVariable(*var);
m_summaries[contract].emplace(function, createSummaryBlock(*function, *contract));

View File

@ -132,7 +132,7 @@ vector<smtutil::Expression> currentBlockVariables(FunctionDefinition const& _fun
{
return currentFunctionVariables(_function, _contract, _context) +
applyMap(
_function.localVariables(),
SMTEncoder::localVariablesIncludingModifiers(_function),
[&](auto _var) { return _context.variable(*_var)->currentValue(); }
);
}

View File

@ -90,7 +90,7 @@ SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefini
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
return make_shared<FunctionSort>(
fSort->domain + applyMap(_function.localVariables(), smtSort),
fSort->domain + applyMap(SMTEncoder::localVariablesIncludingModifiers(_function), smtSort),
SortProvider::boolSort
);
}

View File

@ -1986,7 +1986,12 @@ void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _fu
m_arrayAssignmentHappened = true;
}
for (auto const& variable: _function.localVariables())
vector<VariableDeclaration const*> localVars;
if (auto const* fun = dynamic_cast<FunctionDefinition const*>(&_function))
localVars = localVariablesIncludingModifiers(*fun);
else
localVars = _function.localVariables();
for (auto const& variable: localVars)
if (createVariable(*variable))
{
m_context.newValue(*variable);
@ -2026,7 +2031,7 @@ void SMTEncoder::initializeStateVariables(ContractDefinition const& _contract)
void SMTEncoder::createLocalVariables(FunctionDefinition const& _function)
{
for (auto const& variable: _function.localVariables())
for (auto const& variable: localVariablesIncludingModifiers(_function))
createVariable(*variable);
for (auto const& param: _function.parameters())
@ -2039,7 +2044,7 @@ void SMTEncoder::createLocalVariables(FunctionDefinition const& _function)
void SMTEncoder::initializeLocalVariables(FunctionDefinition const& _function)
{
for (auto const& variable: _function.localVariables())
for (auto const& variable: localVariablesIncludingModifiers(_function))
{
solAssert(m_context.knownVariable(*variable), "");
m_context.setZeroValue(*variable);
@ -2294,7 +2299,7 @@ void SMTEncoder::clearIndices(ContractDefinition const* _contract, FunctionDefin
{
for (auto const& var: _function->parameters() + _function->returnParameters())
m_context.variable(*var)->resetIndex();
for (auto const& var: _function->localVariables())
for (auto const& var: localVariablesIncludingModifiers(*_function))
m_context.variable(*var)->resetIndex();
}
m_context.state().reset();
@ -2429,6 +2434,38 @@ vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedA
return stateVariablesIncludingInheritedAndPrivate(dynamic_cast<ContractDefinition const&>(*_function.scope()));
}
vector<VariableDeclaration const*> SMTEncoder::localVariablesIncludingModifiers(FunctionDefinition const& _function)
{
return _function.localVariables() + modifiersVariables(_function);
}
vector<VariableDeclaration const*> SMTEncoder::modifiersVariables(FunctionDefinition const& _function)
{
struct BlockVars: ASTConstVisitor
{
BlockVars(Block const& _block) { _block.accept(*this); }
void endVisit(VariableDeclaration const& _var) { vars.push_back(&_var); }
vector<VariableDeclaration const*> vars;
};
vector<VariableDeclaration const*> vars;
set<ModifierDefinition const*> visited;
for (auto invok: _function.modifiers())
{
if (!invok)
continue;
auto decl = invok->name().annotation().referencedDeclaration;
auto const* modifier = dynamic_cast<ModifierDefinition const*>(decl);
if (!modifier || visited.count(modifier))
continue;
visited.insert(modifier);
vars += applyMap(modifier->parameters(), [](auto _var) { return _var.get(); });
vars += BlockVars(modifier->body()).vars;
}
return vars;
}
SourceUnit const* SMTEncoder::sourceUnitContaining(Scopable const& _scopable)
{
for (auto const* s = &_scopable; s; s = dynamic_cast<Scopable const*>(s->scope()))

View File

@ -71,6 +71,9 @@ public:
static std::vector<VariableDeclaration const*> stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract);
static std::vector<VariableDeclaration const*> stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function);
static std::vector<VariableDeclaration const*> localVariablesIncludingModifiers(FunctionDefinition const& _function);
static std::vector<VariableDeclaration const*> modifiersVariables(FunctionDefinition const& _function);
/// @returns the SourceUnit that contains _scopable.
static SourceUnit const* sourceUnitContaining(Scopable const& _scopable);

View File

@ -1180,8 +1180,6 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
return formatFatalError("JSONError", "Yul mode does not support smtlib2responses.");
if (!_inputsAndSettings.remappings.empty())
return formatFatalError("JSONError", "Field \"settings.remappings\" cannot be used for Yul.");
if (!_inputsAndSettings.libraries.empty())
return formatFatalError("JSONError", "Field \"settings.libraries\" cannot be used for Yul.");
if (_inputsAndSettings.revertStrings != RevertStrings::Default)
return formatFatalError("JSONError", "Field \"settings.debug.revertStrings\" cannot be used for Yul.");
@ -1234,6 +1232,11 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
MachineAssemblyObject runtimeObject;
tie(object, runtimeObject) = stack.assembleAndGuessRuntime();
if (object.bytecode)
object.bytecode->link(_inputsAndSettings.libraries);
if (runtimeObject.bytecode)
runtimeObject.bytecode->link(_inputsAndSettings.libraries);
for (string const& objectKind: vector<string>{"bytecode", "deployedBytecode"})
if (isArtifactRequested(
_inputsAndSettings.outputSelection,

View File

@ -305,13 +305,23 @@ bytes BinaryTransform::run(Module const& _module)
ret += exportSection(functionIDs);
map<string, pair<size_t, size_t>> subModulePosAndSize;
for (auto const& sub: _module.subModules)
for (auto const& [name, module]: _module.subModules)
{
// TODO should we prefix and / or shorten the name?
bytes data = BinaryTransform::run(sub.second);
size_t length = data.size();
ret += customSection(sub.first, move(data));
subModulePosAndSize[sub.first] = {ret.size() - length, length};
bytes data = BinaryTransform::run(module);
size_t const length = data.size();
ret += customSection(name, move(data));
// Skip all the previous sections and the size field of this current custom section.
size_t const offset = ret.size() - length;
subModulePosAndSize[name] = {offset, length};
}
for (auto const& [name, data]: _module.customSections)
{
size_t const length = data.size();
ret += customSection(name, data);
// Skip all the previous sections and the size field of this current custom section.
size_t const offset = ret.size() - length;
subModulePosAndSize[name] = {offset, length};
}
BinaryTransform bt(
@ -663,9 +673,11 @@ bytes BinaryTransform::globalSection(vector<wasm::GlobalVariableDeclaration> con
bytes BinaryTransform::exportSection(map<string, size_t> const& _functionIDs)
{
bytes result = lebEncode(2);
bool hasMain = _functionIDs.count("main");
bytes result = lebEncode(hasMain ? 2 : 1);
result += encodeName("memory") + toBytes(Export::Memory) + lebEncode(0);
result += encodeName("main") + toBytes(Export::Function) + lebEncode(_functionIDs.at("main"));
if (hasMain)
result += encodeName("main") + toBytes(Export::Function) + lebEncode(_functionIDs.at("main"));
return makeSection(Section::EXPORT, move(result));
}

View File

@ -112,6 +112,8 @@ private:
std::map<std::string, size_t> const m_globalIDs;
std::map<std::string, size_t> const m_functionIDs;
std::map<std::string, size_t> const m_functionTypes;
/// The map of submodules, where the pair refers to the [offset, length]. The offset is
/// an absolute offset within the resulting assembled bytecode.
std::map<std::string, std::pair<size_t, size_t>> const m_subModulePosAndSize;
std::map<std::string, size_t> m_locals;

View File

@ -44,6 +44,11 @@ string TextTransform::run(wasm::Module const& _module)
" ;; sub-module \"" +
sub.first +
"\" will be encoded as custom section in binary here, but is skipped in text mode.\n";
for (auto const& data: _module.customSections)
ret +=
" ;; custom-section \"" +
data.first +
"\" will be encoded as custom section in binary here, but is skipped in text mode.\n";
for (wasm::FunctionImport const& imp: _module.imports)
{
ret += " (import \"" + imp.module + "\" \"" + imp.externalName + "\" (func $" + imp.internalName;
@ -56,8 +61,13 @@ string TextTransform::run(wasm::Module const& _module)
// allocate one 64k page of memory and make it available to the Ethereum client
ret += " (memory $memory (export \"memory\") 1)\n";
// export the main function
ret += " (export \"main\" (func $main))\n";
for (auto const& f: _module.functions)
if (f.name == "main")
{
// export the main function
ret += " (export \"main\" (func $main))\n";
break;
}
for (auto const& g: _module.globals)
ret += " (global $" + g.variableName + " (mut " + encodeType(g.type) + ") (" + encodeType(g.type) + ".const 0))\n";

View File

@ -21,6 +21,8 @@
#pragma once
#include <libsolutil/Common.h>
#include <variant>
#include <string>
#include <vector>
@ -108,6 +110,7 @@ struct Module
std::vector<FunctionImport> imports;
std::vector<FunctionDefinition> functions;
std::map<std::string, Module> subModules;
std::map<std::string, bytes> customSections;
};
}

View File

@ -51,8 +51,10 @@ wasm::Module WasmObjectCompiler::run(Object& _object)
for (auto& subNode: _object.subObjects)
if (Object* subObject = dynamic_cast<Object*>(subNode.get()))
module.subModules[subObject->name.str()] = run(*subObject);
else if (Data* subObject = dynamic_cast<Data*>(subNode.get()))
module.customSections[subObject->name.str()] = subObject->data;
else
yulAssert(false, "Data is not yet supported for Wasm.");
yulAssert(false, "");
return module;
}

View File

@ -1883,8 +1883,29 @@ bool CommandLineInterface::assemble(
if (_language != yul::AssemblyStack::Language::Ewasm && _targetMachine == yul::AssemblyStack::Machine::Ewasm)
{
stack.translate(yul::AssemblyStack::Language::Ewasm);
stack.optimize();
try
{
stack.translate(yul::AssemblyStack::Language::Ewasm);
stack.optimize();
}
catch (Exception const& _exception)
{
serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl;
return false;
}
catch (std::exception const& _e)
{
serr() <<
"Unknown exception during compilation" <<
(_e.what() ? ": " + string(_e.what()) : ".") <<
endl;
return false;
}
catch (...)
{
serr() << "Unknown exception in assembler." << endl;
return false;
}
sout() << endl << "==========================" << endl;
sout() << endl << "Translated source:" << endl;
@ -1895,6 +1916,7 @@ bool CommandLineInterface::assemble(
try
{
object = stack.assemble(_targetMachine);
object.bytecode->link(m_libraries);
}
catch (Exception const& _exception)
{

View File

@ -112,20 +112,34 @@ function test_solc_behaviour()
sed -i.bak -e 's/{[^{]*Warning: This is a pre-release compiler version[^}]*},\{0,1\}//' "$stdout_path"
sed -i.bak -E -e 's/ Consider adding \\"pragma solidity \^[0-9.]*;\\"//g' "$stdout_path"
sed -i.bak -e 's/"errors":\[\],\{0,1\}//' "$stdout_path"
# Remove explicit bytecode and references to bytecode offsets
sed -i.bak -E -e 's/\"object\":\"[a-f0-9]+\"/\"object\":\"bytecode removed\"/g' "$stdout_path"
sed -i.bak -E -e 's/\"opcodes\":\"[^"]+\"/\"opcodes\":\"opcodes removed\"/g' "$stdout_path"
sed -i.bak -E -e 's/\"sourceMap\":\"[0-9:;-]+\"/\"sourceMap\":\"sourceMap removed\"/g' "$stdout_path"
sed -i.bak -E -e 's/\"opcodes\":\"[^"]+\"/\"opcodes\":\"<OPCODES REMOVED>\"/g' "$stdout_path"
sed -i.bak -E -e 's/\"sourceMap\":\"[0-9:;-]+\"/\"sourceMap\":\"<SOURCEMAP REMOVED>\"/g' "$stdout_path"
# Remove bytecode (but not linker references).
sed -i.bak -E -e 's/(\"object\":\")[0-9a-f]+([^"]*\")/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
sed -i.bak -E -e 's/(\"object\":\"[^"]+\$__)[0-9a-f]+(\")/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
sed -i.bak -E -e 's/(__\$[0-9a-f]{34}\$__)[0-9a-f]+(__\$[0-9a-f]{34}\$__)/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
# Replace escaped newlines by actual newlines for readability
sed -i.bak -E -e 's/\\n/\'$'\n/g' "$stdout_path"
rm "$stdout_path.bak"
else
sed -i.bak -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e '/^Warning (3805): This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1AUXDATA REMOVED/' "$stdout_path"
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1<AUXDATA REMOVED>/' "$stdout_path"
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
sed -i.bak -e 's/\(Unimplemented feature error: .* in \).*$/\1FILENAME REMOVED/' "$stderr_path"
sed -i.bak -e 's/"version": "[^"]*"/"version": "VERSION REMOVED"/' "$stdout_path"
sed -i.bak -e 's/\(Unimplemented feature error: .* in \).*$/\1<FILENAME REMOVED>/' "$stderr_path"
sed -i.bak -e 's/"version": "[^"]*"/"version": "<VERSION REMOVED>"/' "$stdout_path"
# Remove bytecode (but not linker references). Since non-JSON output is unstructured,
# use metadata markers for detection to have some confidence that it's actually bytecode
# and not some random word.
# 64697066735822 = hex encoding of 0x64 'i' 'p' 'f' 's' 0x58 0x22
# 64736f6c63 = hex encoding of 0x64 's' 'o' 'l' 'c'
sed -i.bak -E -e 's/[0-9a-f]*64697066735822[0-9a-f]+64736f6c63[0-9a-f]+/<BYTECODE REMOVED>/g' "$stdout_path"
sed -i.bak -E -e 's/(__\$[0-9a-f]{34}\$__)[0-9a-f]+(__\$[0-9a-f]{34}\$__)/\1<BYTECODE REMOVED>\2/g' "$stdout_path"
sed -i.bak -E -e 's/[0-9a-f]+((__\$[0-9a-f]{34}\$__)*<BYTECODE REMOVED>)/<BYTECODE REMOVED>\1/g' "$stdout_path"
# Remove trailing empty lines. Needs a line break to make OSX sed happy.
sed -i.bak -e '1{/^$/d
}' "$stderr_path"

View File

@ -731,5 +731,5 @@
]
}
},
"version": "VERSION REMOVED"
"version": "<VERSION REMOVED>"
}

View File

@ -50,5 +50,5 @@ sub_0: assembly {
/* "dup_opt_peephole/input.sol":0:111 contract C {... */
stop
auxdata: AUXDATA REMOVED
auxdata: <AUXDATA REMOVED>
}

View File

@ -0,0 +1 @@
--bin --bin-runtime --libraries linking_solidity/input.sol:L:0x1234567890123456789012345678901234567890

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
library L {
function f() external {}
}
contract C {
function foo() public {
L.f();
}
}

View File

@ -0,0 +1,12 @@
======= linking_solidity/input.sol:C =======
Binary:
<BYTECODE REMOVED>
Binary of the runtime part:
<BYTECODE REMOVED>
======= linking_solidity/input.sol:L =======
Binary:
<BYTECODE REMOVED>
Binary of the runtime part:
<BYTECODE REMOVED>

View File

@ -0,0 +1 @@
--bin --bin-runtime --libraries linking_solidity_unresolved_references/input.sol:L1:0x1234567890123456789012345678901234567890

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
library L1 {
function f() external {}
}
library L2 {
function f() external {}
}
contract C {
function foo() public {
L1.f();
L2.f();
L1.f();
L2.f();
L1.f();
}
}

View File

@ -0,0 +1,24 @@
======= linking_solidity_unresolved_references/input.sol:C =======
Binary:
<BYTECODE REMOVED>__$8ef13d1c56d5343bf69cf9444272079aa5$__<BYTECODE REMOVED>__$8ef13d1c56d5343bf69cf9444272079aa5$__<BYTECODE REMOVED>
// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2
// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2
Binary of the runtime part:
<BYTECODE REMOVED>__$8ef13d1c56d5343bf69cf9444272079aa5$__<BYTECODE REMOVED>__$8ef13d1c56d5343bf69cf9444272079aa5$__<BYTECODE REMOVED>
// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2
// $8ef13d1c56d5343bf69cf9444272079aa5$ -> linking_solidity_unresolved_references/input.sol:L2
======= linking_solidity_unresolved_references/input.sol:L1 =======
Binary:
<BYTECODE REMOVED>
Binary of the runtime part:
<BYTECODE REMOVED>
======= linking_solidity_unresolved_references/input.sol:L2 =======
Binary:
<BYTECODE REMOVED>
Binary of the runtime part:
<BYTECODE REMOVED>

View File

@ -0,0 +1,33 @@
{
"language": "Solidity",
"sources": {
"A": {
"content": "
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
library L {
function f() external {}
}
contract C {
function foo() public {
L.f();
}
}
"
}
},
"settings": {
"libraries": {
"contract/test.sol": {
"L": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,33 @@
{
"language": "Solidity",
"sources": {
"A": {
"content": "
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
library L {
function f() external {}
}
contract C {
function foo() public {
L.f();
}
}
"
}
},
"settings": {
"libraries": {
"contract/test\"test.sol": {
"L": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,41 @@
{
"language": "Solidity",
"sources": {
"A": {
"content": "
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
library L1 {
function f() external {}
}
library L2 {
function f() external {}
}
contract C {
function foo() public {
L1.f();
L2.f();
L1.f();
L2.f();
L1.f();
}
}
"
}
},
"settings": {
"libraries": {
"contract/test.sol": {
"L1": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{"A":{"L2":[{"length":20,"start":184},{"length":20,"start":368}]}},"object":"<BYTECODE REMOVED>__$622b2f540b6a16ff5db7bea656ad8fcf4f$__<BYTECODE REMOVED>__$622b2f540b6a16ff5db7bea656ad8fcf4f$__<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,20 @@
{
"language": "Yul",
"sources": {
"A": {
"content": "object \"a\" { code { let addr := linkersymbol(\"contract/test.sol:L\") } }"
}
},
"settings": {
"libraries": {
"contract/test.sol": {
"L": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"*": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"a":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","formattedMessage":"Yul is still experimental. Please use the output with care.","message":"Yul is still experimental. Please use the output with care.","severity":"warning","type":"Warning"}]}

View File

@ -0,0 +1,20 @@
{
"language": "Yul",
"sources": {
"A": {
"content": "object \"a\" { code { let addr := linkersymbol(\"contract/test\\\".sol:L\") } }"
}
},
"settings": {
"libraries": {
"contract/test\".sol": {
"L": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"*": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"a":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","formattedMessage":"Yul is still experimental. Please use the output with care.","message":"Yul is still experimental. Please use the output with care.","severity":"warning","type":"Warning"}]}

View File

@ -0,0 +1,20 @@
{
"language": "Yul",
"sources": {
"A": {
"content": "object \"a\" { code { let addr1 := linkersymbol(\"contract/test.sol:L1\") let addr2 := linkersymbol(\"contract/test.sol:L2\") } }"
}
},
"settings": {
"libraries": {
"contract/test.sol": {
"L1": "0x1234567890123456789012345678901234567890"
}
},
"outputSelection": {
"*": {
"*": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
}
}
}
}

View File

@ -0,0 +1 @@
{"contracts":{"A":{"a":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{"contract/test.sol":{"L2":[{"length":20,"start":22}]}},"object":"<BYTECODE REMOVED>__$fb58009a6b1ecea3b9d99bedd645df4ec3$__<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","formattedMessage":"Yul is still experimental. Please use the output with care.","message":"Yul is still experimental. Please use the output with care.","severity":"warning","type":"Warning"}]}

View File

@ -0,0 +1 @@
--strict-assembly --libraries contract/test.sol:L:0x1234567890123456789012345678901234567890

View File

@ -0,0 +1 @@
Warning: Yul is still experimental. Please use the output with care.

View File

@ -0,0 +1,5 @@
object "a" {
code {
let addr := linkersymbol("contract/test.sol:L")
}
}

View File

@ -0,0 +1,18 @@
======= linking_strict_assembly/input.yul (EVM) =======
Pretty printed source:
object "a" {
code {
let addr := linkersymbol("contract/test.sol:L")
}
}
Binary representation:
73123456789012345678901234567890123456789050
Text representation:
linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612")
/* "linking_strict_assembly/input.yul":22:85 */
pop

View File

@ -0,0 +1 @@
--strict-assembly --libraries contract/test.sol:L1:0x1234567890123456789012345678901234567890

View File

@ -0,0 +1 @@
Warning: Yul is still experimental. Please use the output with care.

View File

@ -0,0 +1,6 @@
object "a" {
code {
let addr1 := linkersymbol("contract/test.sol:L1")
let addr2 := linkersymbol("contract/test.sol:L2")
}
}

View File

@ -0,0 +1,22 @@
======= linking_strict_assembly_unresolved_references/input.yul (EVM) =======
Pretty printed source:
object "a" {
code {
let addr1 := linkersymbol("contract/test.sol:L1")
let addr2 := linkersymbol("contract/test.sol:L2")
}
}
Binary representation:
73123456789012345678901234567890123456789073__$fb58009a6b1ecea3b9d99bedd645df4ec3$__5050
Text representation:
linkerSymbol("05b0326038374a21e0895480a58bda0768cdcc04c8d18f154362d1ca5223d245")
/* "linking_strict_assembly_unresolved_references/input.yul":32:81 */
linkerSymbol("fb58009a6b1ecea3b9d99bedd645df4ec308f17bc0087e5f39d078f77f809177")
/* "linking_strict_assembly_unresolved_references/input.yul":22:145 */
pop
pop

View File

@ -87,5 +87,5 @@ sub_0: assembly {
tag_7:
jump // out
auxdata: AUXDATA REMOVED
auxdata: <AUXDATA REMOVED>
}

View File

@ -83,5 +83,5 @@ sub_0: assembly {
dup1
revert
auxdata: AUXDATA REMOVED
auxdata: <AUXDATA REMOVED>
}

View File

@ -1,4 +1,4 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }

View File

@ -1,4 +1,4 @@
{"contracts":{"a.sol":{"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }

View File

@ -1,4 +1,4 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"B2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}},"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}},"B2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,4 +1,4 @@
{"contracts":{"b.sol":{"B2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"b.sol":{"B2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}},"A2":{"evm":{"bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"generatedSources":[],"immutableReferences":{"3":[{"length":32,"start":77}]},"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"36:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;108:7;126:1;119:8;;74:56;:::o"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"generatedSources":[],"immutableReferences":{"3":[{"length":32,"start":77}]},"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"36:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;108:7;126:1;119:8;;74:56;:::o"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0}}}

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@
sstore
/* \"A\":0:42 */
pop
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"object\" {
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)

View File

@ -13,7 +13,7 @@
pop
stop
data_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45 616263
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"NamedObject\" {
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
code {
let x := dataoffset(\"DataName\")
sstore(add(x, 0), 0)

View File

@ -22,7 +22,7 @@ sub_0: assembly {
/* \"A\":137:149 */
revert
}
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"},"deployedBytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"NamedObject\" {
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"},"deployedBytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"NamedObject\" {
code {
let x := dataoffset(\"DataName\")
sstore(add(x, 0), 0)

View File

@ -13,7 +13,7 @@
/* \"A\":20:40 */
sstore
pop
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"object\" {
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)

View File

@ -5,7 +5,7 @@
mload
/* \"A\":20:40 */
sstore
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}},"ir":"object \"object\" {
","bytecode":{"generatedSources":[],"linkReferences":{},"object":"<BYTECODE REMOVED>","opcodes":"<OPCODES REMOVED>","sourceMap":"<SOURCEMAP REMOVED>"}},"ir":"object \"object\" {
code {
let x := mload(0)
sstore(add(x, 0), 0)

View File

@ -1,4 +1,4 @@
Error (1834): Unimplemented feature error: Copying from storage to storage is not yet implemented. in FILENAME REMOVED
Error (1834): Unimplemented feature error: Copying from storage to storage is not yet implemented. in <FILENAME REMOVED>
--> yul_unimplemented/input.sol:7:9:
|
7 | a = b;

View File

@ -97,6 +97,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
{
asmStack.optimize();
obj = std::move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode);
obj.link(_libraryAddresses);
break;
}
catch (...)

View File

@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint x;
modifier m(uint z) {
uint y = 3;
if (z == 10)
x = 2 + y;
_;
if (z == 10)
x = 4 + y;
}
function f() m(10) internal {
x = 3;
}
function g() public {
x = 0;
f();
assert(x == 7);
// Fails
assert(x == 6);
}
}
// ----
// Warning 6328: (359-373): CHC: Assertion violation happens here.

View File

@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint x;
modifier m(uint z) {
uint y = 3;
if (z == 10)
x = 2 + y;
_;
if (z == 10)
x = 4 + y;
}
function f() m(10) m(12) internal {
x = 3;
}
function g() public {
x = 0;
f();
assert(x == 3);
// Fails
assert(x == 6);
}
}
// ----
// Warning 6328: (365-379): CHC: Assertion violation happens here.

View File

@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint x;
modifier m(uint z) {
uint y = 3;
if (z == 10)
x = 2 + y;
_;
if (z == 10)
x = 4 + y;
}
function f() m(8) internal {
x = 3;
}
function g() public {
x = 0;
f();
assert(x == 3);
// Fails
assert(x == 6);
}
}
// ----
// Warning 6328: (358-372): CHC: Assertion violation happens here.

View File

@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint x;
modifier m(uint z) {
uint y = 3;
if (z >= 10)
x = 2 + y;
_;
if (z >= 10)
x = 4 + y;
}
function f() m(10) m(12) internal {
x = 3;
}
function g() public {
x = 0;
f();
assert(x == 7);
// Fails
assert(x == 6);
}
}
// ----
// Warning 6328: (365-379): CHC: Assertion violation happens here.

View File

@ -36,11 +36,9 @@
using namespace solidity;
using namespace solidity::util;
using namespace solidity::langutil;
using namespace solidity::frontend;
using namespace solidity::frontend::test;
using namespace std;
using namespace soltest;
bytes BytesUtils::alignLeft(bytes _bytes)
{

View File

@ -41,7 +41,6 @@ using namespace solidity::util;
using namespace solidity::langutil;
using namespace solidity::frontend::test;
using namespace std;
using namespace soltest;
namespace
{

View File

@ -16,7 +16,6 @@
#include <libsolutil/AnsiColorized.h>
#include <libsolutil/CommonData.h>
#include <libsolidity/ast/Types.h>
namespace solidity::frontend::test
{

View File

@ -34,11 +34,11 @@
#include <stdexcept>
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
using namespace solidity::frontend::test;
using namespace std;
using namespace soltest;
using Token = soltest::Token;
char TestFileParser::Scanner::peek() const noexcept
{
@ -158,7 +158,7 @@ vector<solidity::frontend::test::FunctionCall> TestFileParser::parseFunctionCall
return calls;
}
bool TestFileParser::accept(soltest::Token _token, bool const _expect)
bool TestFileParser::accept(Token _token, bool const _expect)
{
if (m_scanner.currentToken() != _token)
return false;
@ -167,7 +167,7 @@ bool TestFileParser::accept(soltest::Token _token, bool const _expect)
return true;
}
bool TestFileParser::expect(soltest::Token _token, bool const _advance)
bool TestFileParser::expect(Token _token, bool const _advance)
{
if (m_scanner.currentToken() != _token || m_scanner.currentToken() == Token::Invalid)
throw TestParserError(
@ -484,31 +484,31 @@ void TestFileParser::Scanner::readStream(istream& _stream)
void TestFileParser::Scanner::scanNextToken()
{
using namespace langutil;
// Make code coverage happy.
assert(formatToken(Token::NUM_TOKENS) == "");
auto detectKeyword = [](std::string const& _literal = "") -> TokenDesc {
if (_literal == "true") return TokenDesc{Token::Boolean, _literal};
if (_literal == "false") return TokenDesc{Token::Boolean, _literal};
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
if (_literal == "wei") return TokenDesc{Token::Wei, _literal};
if (_literal == "left") return TokenDesc{Token::Left, _literal};
if (_literal == "library") return TokenDesc{Token::Library, _literal};
if (_literal == "right") return TokenDesc{Token::Right, _literal};
if (_literal == "hex") return TokenDesc{Token::Hex, _literal};
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
if (_literal == "storage") return TokenDesc{Token::Storage, _literal};
return TokenDesc{Token::Identifier, _literal};
auto detectKeyword = [](std::string const& _literal = "") -> std::pair<Token, std::string> {
if (_literal == "true") return {Token::Boolean, "true"};
if (_literal == "false") return {Token::Boolean, "false"};
if (_literal == "ether") return {Token::Ether, ""};
if (_literal == "wei") return {Token::Wei, ""};
if (_literal == "left") return {Token::Left, ""};
if (_literal == "library") return {Token::Library, ""};
if (_literal == "right") return {Token::Right, ""};
if (_literal == "hex") return {Token::Hex, ""};
if (_literal == "FAILURE") return {Token::Failure, ""};
if (_literal == "storage") return {Token::Storage, ""};
return {Token::Identifier, _literal};
};
auto selectToken = [this](Token _token, std::optional<std::string> _literal = std::nullopt) -> TokenDesc {
auto selectToken = [this](Token _token, std::string const& _literal = "") {
advance();
return make_pair(_token, _literal.has_value() ? *_literal : formatToken(_token));
m_currentToken = _token;
m_currentLiteral = _literal;
};
TokenDesc token = make_pair(Token::Unknown, "");
m_currentToken = Token::Unknown;
m_currentLiteral = "";
do
{
switch(current())
@ -516,71 +516,73 @@ void TestFileParser::Scanner::scanNextToken()
case '/':
advance();
if (current() == '/')
token = selectToken(Token::Newline);
selectToken(Token::Newline);
else
token = selectToken(Token::Invalid);
selectToken(Token::Invalid);
break;
case '-':
if (peek() == '>')
{
advance();
token = selectToken(Token::Arrow);
selectToken(Token::Arrow);
}
else
token = selectToken(Token::Sub);
selectToken(Token::Sub);
break;
case ':':
token = selectToken(Token::Colon);
selectToken(Token::Colon);
break;
case '#':
token = selectToken(Token::Comment, scanComment());
selectToken(Token::Comment, scanComment());
break;
case ',':
token = selectToken(Token::Comma);
selectToken(Token::Comma);
break;
case '(':
token = selectToken(Token::LParen);
selectToken(Token::LParen);
break;
case ')':
token = selectToken(Token::RParen);
selectToken(Token::RParen);
break;
case '[':
token = selectToken(Token::LBrack);
selectToken(Token::LBrack);
break;
case ']':
token = selectToken(Token::RBrack);
selectToken(Token::RBrack);
break;
case '\"':
token = selectToken(Token::String, scanString());
selectToken(Token::String, scanString());
break;
default:
if (isIdentifierStart(current()))
if (langutil::isIdentifierStart(current()))
{
TokenDesc detectedToken = detectKeyword(scanIdentifierOrKeyword());
token = selectToken(detectedToken.first, detectedToken.second);
std::tie(m_currentToken, m_currentLiteral) = detectKeyword(scanIdentifierOrKeyword());
advance();
}
else if (isDecimalDigit(current()))
else if (langutil::isDecimalDigit(current()))
{
if (current() == '0' && peek() == 'x')
{
advance();
advance();
token = selectToken(Token::HexNumber, "0x" + scanHexNumber());
selectToken(Token::HexNumber, "0x" + scanHexNumber());
}
else
token = selectToken(Token::Number, scanDecimalNumber());
selectToken(Token::Number, scanDecimalNumber());
}
else if (isWhiteSpace(current()))
token = selectToken(Token::Whitespace);
else if (langutil::isWhiteSpace(current()))
selectToken(Token::Whitespace);
else if (isEndOfLine())
token = make_pair(Token::EOS, "EOS");
{
m_currentToken = Token::EOS;
m_currentLiteral = "";
}
else
throw TestParserError("Unexpected character: '" + string{current()} + "'");
break;
}
}
while (token.first == Token::Whitespace);
m_currentToken = token;
while (m_currentToken == Token::Whitespace);
}
string TestFileParser::Scanner::scanComment()

View File

@ -15,7 +15,6 @@
#pragma once
#include <libsolutil/CommonData.h>
#include <libsolidity/ast/Types.h>
#include <liblangutil/Exceptions.h>
#include <test/libsolidity/util/SoltestTypes.h>
@ -64,7 +63,6 @@ public:
std::vector<FunctionCall> parseFunctionCalls(std::size_t _lineOffset);
private:
using Token = soltest::Token;
/**
* Token scanner that is used internally to abstract away character traversal.
*/
@ -81,8 +79,8 @@ private:
/// Reads character stream and creates token.
void scanNextToken();
soltest::Token currentToken() { return m_currentToken.first; }
std::string currentLiteral() { return m_currentToken.second; }
soltest::Token currentToken() { return m_currentToken; }
std::string currentLiteral() { return m_currentLiteral; }
std::string scanComment();
std::string scanIdentifierOrKeyword();
@ -92,8 +90,6 @@ private:
char scanHexPart();
private:
using TokenDesc = std::pair<Token, std::string>;
/// Advances current position in the input stream.
void advance(unsigned n = 1)
{
@ -120,7 +116,8 @@ private:
std::string m_line;
std::string::const_iterator m_char;
TokenDesc m_currentToken;
std::string m_currentLiteral;
soltest::Token m_currentToken = soltest::Token::Unknown;
};
bool accept(soltest::Token _token, bool const _expect = false);

View File

@ -30,6 +30,8 @@ using namespace solidity::util;
using namespace solidity::frontend::test;
using namespace std;
using Token = soltest::Token;
string TestFunctionCall::format(
ErrorReporter& _errorReporter,
string const& _linePrefix,
@ -37,9 +39,6 @@ string TestFunctionCall::format(
bool const _highlight
) const
{
using namespace soltest;
using Token = soltest::Token;
stringstream stream;
bool highlight = !matchesExpectation() && _highlight;
@ -279,8 +278,6 @@ string TestFunctionCall::formatFailure(
bool _highlight
) const
{
using Token = soltest::Token;
stringstream os;
os << formatToken(Token::Failure);

View File

@ -17,7 +17,6 @@
#include <test/libsolidity/util/TestFileParser.h>
#include <test/libsolidity/util/SoltestErrors.h>
#include <libsolidity/ast/Types.h>
#include <liblangutil/Exceptions.h>
#include <libsolutil/AnsiColorized.h>
#include <libsolutil/CommonData.h>