mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7450 from ethereum/stripRevertMessages
Provide different options for reason strings.
This commit is contained in:
commit
d633d375e7
@ -31,6 +31,9 @@ Language Features:
|
|||||||
* Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore.
|
* Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore.
|
||||||
* Yul: Introduce ``leave`` statement that exits the current function.
|
* Yul: Introduce ``leave`` statement that exits the current function.
|
||||||
|
|
||||||
|
Compiler Features:
|
||||||
|
* Allow revert strings to be stripped from the binary using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting.
|
||||||
|
|
||||||
|
|
||||||
### 0.5.13 (unreleased)
|
### 0.5.13 (unreleased)
|
||||||
|
|
||||||
|
@ -234,6 +234,16 @@ Input Description
|
|||||||
// Affects type checking and code generation. Can be homestead,
|
// Affects type checking and code generation. Can be homestead,
|
||||||
// tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg, istanbul or berlin
|
// tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg, istanbul or berlin
|
||||||
"evmVersion": "byzantium",
|
"evmVersion": "byzantium",
|
||||||
|
// Optional: Debugging settings
|
||||||
|
"debug": {
|
||||||
|
// How to treat revert (and require) reason strings. Settings are
|
||||||
|
// "default", "strip", "debug" and "verboseDebug".
|
||||||
|
// "default" does not inject compiler-generated revert strings and keeps user-supplied ones.
|
||||||
|
// "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects
|
||||||
|
// "debug" injects strings for compiler-generated internal reverts (not yet implemented)
|
||||||
|
// "verboseDebug" even appends further information to user-supplied revert strings (not yet implemented)
|
||||||
|
"revertStrings": "default"
|
||||||
|
}
|
||||||
// Metadata settings (optional)
|
// Metadata settings (optional)
|
||||||
"metadata": {
|
"metadata": {
|
||||||
// Use only literal content and not URLs (false by default)
|
// Use only literal content and not URLs (false by default)
|
||||||
|
@ -101,6 +101,7 @@ set(sources
|
|||||||
interface/ABI.h
|
interface/ABI.h
|
||||||
interface/CompilerStack.cpp
|
interface/CompilerStack.cpp
|
||||||
interface/CompilerStack.h
|
interface/CompilerStack.h
|
||||||
|
interface/DebugSettings.h
|
||||||
interface/GasEstimator.cpp
|
interface/GasEstimator.cpp
|
||||||
interface/GasEstimator.h
|
interface/GasEstimator.h
|
||||||
interface/Natspec.cpp
|
interface/Natspec.cpp
|
||||||
|
@ -35,7 +35,7 @@ void Compiler::compileContract(
|
|||||||
bytes const& _metadata
|
bytes const& _metadata
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimiserSettings);
|
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimiserSettings, m_revertStrings);
|
||||||
runtimeCompiler.compileContract(_contract, _otherCompilers);
|
runtimeCompiler.compileContract(_contract, _otherCompilers);
|
||||||
m_runtimeContext.appendAuxiliaryData(_metadata);
|
m_runtimeContext.appendAuxiliaryData(_metadata);
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ void Compiler::compileContract(
|
|||||||
// The creation code will be executed at most once, so we modify the optimizer
|
// The creation code will be executed at most once, so we modify the optimizer
|
||||||
// settings accordingly.
|
// settings accordingly.
|
||||||
creationSettings.expectedExecutionsPerDeployment = 1;
|
creationSettings.expectedExecutionsPerDeployment = 1;
|
||||||
ContractCompiler creationCompiler(&runtimeCompiler, m_context, creationSettings);
|
ContractCompiler creationCompiler(&runtimeCompiler, m_context, creationSettings, m_revertStrings);
|
||||||
m_runtimeSub = creationCompiler.compileConstructor(_contract, _otherCompilers);
|
m_runtimeSub = creationCompiler.compileConstructor(_contract, _otherCompilers);
|
||||||
|
|
||||||
m_context.optimise(m_optimiserSettings);
|
m_context.optimise(m_optimiserSettings);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <libsolidity/codegen/CompilerContext.h>
|
#include <libsolidity/codegen/CompilerContext.h>
|
||||||
#include <libsolidity/interface/OptimiserSettings.h>
|
#include <libsolidity/interface/OptimiserSettings.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -35,8 +36,9 @@ namespace solidity {
|
|||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Compiler(langutil::EVMVersion _evmVersion, OptimiserSettings _optimiserSettings):
|
Compiler(langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings):
|
||||||
m_optimiserSettings(std::move(_optimiserSettings)),
|
m_optimiserSettings(std::move(_optimiserSettings)),
|
||||||
|
m_revertStrings(_revertStrings),
|
||||||
m_runtimeContext(_evmVersion),
|
m_runtimeContext(_evmVersion),
|
||||||
m_context(_evmVersion, &m_runtimeContext)
|
m_context(_evmVersion, &m_runtimeContext)
|
||||||
{ }
|
{ }
|
||||||
@ -79,6 +81,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
OptimiserSettings const m_optimiserSettings;
|
OptimiserSettings const m_optimiserSettings;
|
||||||
|
RevertStrings const m_revertStrings;
|
||||||
CompilerContext m_runtimeContext;
|
CompilerContext m_runtimeContext;
|
||||||
size_t m_runtimeSub = size_t(-1); ///< Identifier of the runtime sub-assembly, if present.
|
size_t m_runtimeSub = size_t(-1); ///< Identifier of the runtime sub-assembly, if present.
|
||||||
CompilerContext m_context;
|
CompilerContext m_context;
|
||||||
|
@ -512,7 +512,7 @@ void ContractCompiler::initializeStateVariables(ContractDefinition const& _contr
|
|||||||
solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library.");
|
solAssert(!_contract.isLibrary(), "Tried to initialize state variables of library.");
|
||||||
for (VariableDeclaration const* variable: _contract.stateVariables())
|
for (VariableDeclaration const* variable: _contract.stateVariables())
|
||||||
if (variable->value() && !variable->isConstant())
|
if (variable->value() && !variable->isConstant())
|
||||||
ExpressionCompiler(m_context, m_optimiserSettings.runOrderLiterals).appendStateVariableInitialization(*variable);
|
ExpressionCompiler(m_context, m_revertStrings, m_optimiserSettings.runOrderLiterals).appendStateVariableInitialization(*variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration)
|
bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration)
|
||||||
@ -525,9 +525,11 @@ bool ContractCompiler::visit(VariableDeclaration const& _variableDeclaration)
|
|||||||
m_continueTags.clear();
|
m_continueTags.clear();
|
||||||
|
|
||||||
if (_variableDeclaration.isConstant())
|
if (_variableDeclaration.isConstant())
|
||||||
ExpressionCompiler(m_context, m_optimiserSettings.runOrderLiterals).appendConstStateVariableAccessor(_variableDeclaration);
|
ExpressionCompiler(m_context, m_revertStrings, m_optimiserSettings.runOrderLiterals)
|
||||||
|
.appendConstStateVariableAccessor(_variableDeclaration);
|
||||||
else
|
else
|
||||||
ExpressionCompiler(m_context, m_optimiserSettings.runOrderLiterals).appendStateVariableAccessor(_variableDeclaration);
|
ExpressionCompiler(m_context, m_revertStrings, m_optimiserSettings.runOrderLiterals)
|
||||||
|
.appendStateVariableAccessor(_variableDeclaration);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1308,7 +1310,7 @@ void ContractCompiler::appendStackVariableInitialisation(VariableDeclaration con
|
|||||||
|
|
||||||
void ContractCompiler::compileExpression(Expression const& _expression, TypePointer const& _targetType)
|
void ContractCompiler::compileExpression(Expression const& _expression, TypePointer const& _targetType)
|
||||||
{
|
{
|
||||||
ExpressionCompiler expressionCompiler(m_context, m_optimiserSettings.runOrderLiterals);
|
ExpressionCompiler expressionCompiler(m_context, m_revertStrings, m_optimiserSettings.runOrderLiterals);
|
||||||
expressionCompiler.compile(_expression);
|
expressionCompiler.compile(_expression);
|
||||||
if (_targetType)
|
if (_targetType)
|
||||||
CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType);
|
CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <libsolidity/ast/ASTVisitor.h>
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
#include <libsolidity/codegen/CompilerContext.h>
|
#include <libsolidity/codegen/CompilerContext.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@ -43,9 +44,11 @@ public:
|
|||||||
explicit ContractCompiler(
|
explicit ContractCompiler(
|
||||||
ContractCompiler* _runtimeCompiler,
|
ContractCompiler* _runtimeCompiler,
|
||||||
CompilerContext& _context,
|
CompilerContext& _context,
|
||||||
OptimiserSettings _optimiserSettings
|
OptimiserSettings _optimiserSettings,
|
||||||
|
RevertStrings _revertStrings
|
||||||
):
|
):
|
||||||
m_optimiserSettings(std::move(_optimiserSettings)),
|
m_optimiserSettings(std::move(_optimiserSettings)),
|
||||||
|
m_revertStrings(_revertStrings),
|
||||||
m_runtimeCompiler(_runtimeCompiler),
|
m_runtimeCompiler(_runtimeCompiler),
|
||||||
m_context(_context)
|
m_context(_context)
|
||||||
{
|
{
|
||||||
@ -138,6 +141,7 @@ private:
|
|||||||
void storeStackHeight(ASTNode const* _node);
|
void storeStackHeight(ASTNode const* _node);
|
||||||
|
|
||||||
OptimiserSettings const m_optimiserSettings;
|
OptimiserSettings const m_optimiserSettings;
|
||||||
|
RevertStrings const m_revertStrings;
|
||||||
/// Pointer to the runtime compiler in case this is a creation compiler.
|
/// Pointer to the runtime compiler in case this is a creation compiler.
|
||||||
ContractCompiler* m_runtimeCompiler = nullptr;
|
ContractCompiler* m_runtimeCompiler = nullptr;
|
||||||
CompilerContext& m_context;
|
CompilerContext& m_context;
|
||||||
|
@ -703,16 +703,28 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
break;
|
break;
|
||||||
case FunctionType::Kind::Revert:
|
case FunctionType::Kind::Revert:
|
||||||
{
|
{
|
||||||
if (!arguments.empty())
|
if (arguments.empty())
|
||||||
|
m_context.appendRevert();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// function-sel(Error(string)) + encoding
|
// function-sel(Error(string)) + encoding
|
||||||
solAssert(arguments.size() == 1, "");
|
solAssert(arguments.size() == 1, "");
|
||||||
solAssert(function.parameterTypes().size() == 1, "");
|
solAssert(function.parameterTypes().size() == 1, "");
|
||||||
arguments.front()->accept(*this);
|
if (m_revertStrings == RevertStrings::Strip)
|
||||||
utils().revertWithStringData(*arguments.front()->annotation().type);
|
{
|
||||||
|
if (!arguments.front()->annotation().isPure)
|
||||||
|
{
|
||||||
|
arguments.front()->accept(*this);
|
||||||
|
utils().popStackElement(*arguments.front()->annotation().type);
|
||||||
|
}
|
||||||
|
m_context.appendRevert();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arguments.front()->accept(*this);
|
||||||
|
utils().revertWithStringData(*arguments.front()->annotation().type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_context.appendRevert();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FunctionType::Kind::KECCAK256:
|
case FunctionType::Kind::KECCAK256:
|
||||||
@ -977,6 +989,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
case FunctionType::Kind::Require:
|
case FunctionType::Kind::Require:
|
||||||
{
|
{
|
||||||
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), false);
|
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), false);
|
||||||
|
|
||||||
|
bool haveReasonString = arguments.size() > 1 && m_revertStrings != RevertStrings::Strip;
|
||||||
|
|
||||||
if (arguments.size() > 1)
|
if (arguments.size() > 1)
|
||||||
{
|
{
|
||||||
// Users probably expect the second argument to be evaluated
|
// Users probably expect the second argument to be evaluated
|
||||||
@ -984,8 +999,19 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
// function call.
|
// function call.
|
||||||
solAssert(arguments.size() == 2, "");
|
solAssert(arguments.size() == 2, "");
|
||||||
solAssert(function.kind() == FunctionType::Kind::Require, "");
|
solAssert(function.kind() == FunctionType::Kind::Require, "");
|
||||||
arguments.at(1)->accept(*this);
|
if (m_revertStrings == RevertStrings::Strip)
|
||||||
utils().moveIntoStack(1, arguments.at(1)->annotation().type->sizeOnStack());
|
{
|
||||||
|
if (!arguments.at(1)->annotation().isPure)
|
||||||
|
{
|
||||||
|
arguments.at(1)->accept(*this);
|
||||||
|
utils().popStackElement(*arguments.at(1)->annotation().type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arguments.at(1)->accept(*this);
|
||||||
|
utils().moveIntoStack(1, arguments.at(1)->annotation().type->sizeOnStack());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Stack: <error string (unconverted)> <condition>
|
// Stack: <error string (unconverted)> <condition>
|
||||||
// jump if condition was met
|
// jump if condition was met
|
||||||
@ -994,7 +1020,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
if (function.kind() == FunctionType::Kind::Assert)
|
if (function.kind() == FunctionType::Kind::Assert)
|
||||||
// condition was not met, flag an error
|
// condition was not met, flag an error
|
||||||
m_context.appendInvalid();
|
m_context.appendInvalid();
|
||||||
else if (arguments.size() > 1)
|
else if (haveReasonString)
|
||||||
{
|
{
|
||||||
utils().revertWithStringData(*arguments.at(1)->annotation().type);
|
utils().revertWithStringData(*arguments.at(1)->annotation().type);
|
||||||
// Here, the argument is consumed, but in the other branch, it is still there.
|
// Here, the argument is consumed, but in the other branch, it is still there.
|
||||||
@ -1004,7 +1030,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
m_context.appendRevert();
|
m_context.appendRevert();
|
||||||
// the success branch
|
// the success branch
|
||||||
m_context << success;
|
m_context << success;
|
||||||
if (arguments.size() > 1)
|
if (haveReasonString)
|
||||||
utils().popStackElement(*arguments.at(1)->annotation().type);
|
utils().popStackElement(*arguments.at(1)->annotation().type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <libsolidity/ast/ASTVisitor.h>
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
#include <libsolidity/codegen/LValue.h>
|
#include <libsolidity/codegen/LValue.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
#include <liblangutil/Exceptions.h>
|
#include <liblangutil/Exceptions.h>
|
||||||
#include <liblangutil/SourceLocation.h>
|
#include <liblangutil/SourceLocation.h>
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
@ -55,8 +56,15 @@ class ArrayType;
|
|||||||
class ExpressionCompiler: private ASTConstVisitor
|
class ExpressionCompiler: private ASTConstVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ExpressionCompiler(CompilerContext& _compilerContext, bool _optimiseOrderLiterals):
|
ExpressionCompiler(
|
||||||
m_optimiseOrderLiterals(_optimiseOrderLiterals), m_context(_compilerContext) {}
|
CompilerContext& _compilerContext,
|
||||||
|
RevertStrings _revertStrings,
|
||||||
|
bool _optimiseOrderLiterals
|
||||||
|
):
|
||||||
|
m_revertStrings(_revertStrings),
|
||||||
|
m_optimiseOrderLiterals(_optimiseOrderLiterals),
|
||||||
|
m_context(_compilerContext)
|
||||||
|
{}
|
||||||
|
|
||||||
/// Compile the given @a _expression and leave its value on the stack.
|
/// Compile the given @a _expression and leave its value on the stack.
|
||||||
void compile(Expression const& _expression);
|
void compile(Expression const& _expression);
|
||||||
@ -130,6 +138,7 @@ private:
|
|||||||
/// @returns the CompilerUtils object containing the current context.
|
/// @returns the CompilerUtils object containing the current context.
|
||||||
CompilerUtils utils();
|
CompilerUtils utils();
|
||||||
|
|
||||||
|
RevertStrings m_revertStrings;
|
||||||
bool m_optimiseOrderLiterals;
|
bool m_optimiseOrderLiterals;
|
||||||
CompilerContext& m_context;
|
CompilerContext& m_context;
|
||||||
std::unique_ptr<LValue> m_currentLValue;
|
std::unique_ptr<LValue> m_currentLValue;
|
||||||
|
@ -152,6 +152,14 @@ void CompilerStack::setOptimiserSettings(OptimiserSettings _settings)
|
|||||||
m_optimiserSettings = std::move(_settings);
|
m_optimiserSettings = std::move(_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompilerStack::setRevertStringBehaviour(RevertStrings _revertStrings)
|
||||||
|
{
|
||||||
|
if (m_stackState >= ParsingPerformed)
|
||||||
|
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set revert string settings before parsing."));
|
||||||
|
solUnimplementedAssert(_revertStrings == RevertStrings::Default || _revertStrings == RevertStrings::Strip, "");
|
||||||
|
m_revertStrings = _revertStrings;
|
||||||
|
}
|
||||||
|
|
||||||
void CompilerStack::useMetadataLiteralSources(bool _metadataLiteralSources)
|
void CompilerStack::useMetadataLiteralSources(bool _metadataLiteralSources)
|
||||||
{
|
{
|
||||||
if (m_stackState >= ParsingPerformed)
|
if (m_stackState >= ParsingPerformed)
|
||||||
@ -187,6 +195,7 @@ void CompilerStack::reset(bool _keepSettings)
|
|||||||
m_evmVersion = langutil::EVMVersion();
|
m_evmVersion = langutil::EVMVersion();
|
||||||
m_generateIR = false;
|
m_generateIR = false;
|
||||||
m_generateEWasm = false;
|
m_generateEWasm = false;
|
||||||
|
m_revertStrings = RevertStrings::Default;
|
||||||
m_optimiserSettings = OptimiserSettings::minimal();
|
m_optimiserSettings = OptimiserSettings::minimal();
|
||||||
m_metadataLiteralSources = false;
|
m_metadataLiteralSources = false;
|
||||||
m_metadataHash = MetadataHash::IPFS;
|
m_metadataHash = MetadataHash::IPFS;
|
||||||
@ -972,7 +981,7 @@ void CompilerStack::compileContract(
|
|||||||
|
|
||||||
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
|
||||||
|
|
||||||
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_evmVersion, m_optimiserSettings);
|
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_evmVersion, m_revertStrings, m_optimiserSettings);
|
||||||
compiledContract.compiler = compiler;
|
compiledContract.compiler = compiler;
|
||||||
|
|
||||||
bytes cborEncodedMetadata = createCBORMetadata(
|
bytes cborEncodedMetadata = createCBORMetadata(
|
||||||
@ -1171,6 +1180,9 @@ string CompilerStack::createMetadata(Contract const& _contract) const
|
|||||||
meta["settings"]["optimizer"]["details"] = std::move(details);
|
meta["settings"]["optimizer"]["details"] = std::move(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_revertStrings != RevertStrings::Default)
|
||||||
|
meta["settings"]["debug"]["revertStrings"] = revertStringsToString(m_revertStrings);
|
||||||
|
|
||||||
if (m_metadataLiteralSources)
|
if (m_metadataLiteralSources)
|
||||||
meta["settings"]["metadata"]["useLiteralContent"] = true;
|
meta["settings"]["metadata"]["useLiteralContent"] = true;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <libsolidity/interface/ReadFile.h>
|
#include <libsolidity/interface/ReadFile.h>
|
||||||
#include <libsolidity/interface/OptimiserSettings.h>
|
#include <libsolidity/interface/OptimiserSettings.h>
|
||||||
#include <libsolidity/interface/Version.h>
|
#include <libsolidity/interface/Version.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
|
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
@ -145,6 +146,9 @@ public:
|
|||||||
/// Must be set before parsing.
|
/// Must be set before parsing.
|
||||||
void setOptimiserSettings(OptimiserSettings _settings);
|
void setOptimiserSettings(OptimiserSettings _settings);
|
||||||
|
|
||||||
|
/// Sets whether to strip revert strings, add additional strings or do nothing at all.
|
||||||
|
void setRevertStringBehaviour(RevertStrings _revertStrings);
|
||||||
|
|
||||||
/// Set whether or not parser error is desired.
|
/// Set whether or not parser error is desired.
|
||||||
/// When called without an argument it will revert to the default.
|
/// When called without an argument it will revert to the default.
|
||||||
/// Must be set before parsing.
|
/// Must be set before parsing.
|
||||||
@ -414,6 +418,7 @@ private:
|
|||||||
|
|
||||||
ReadCallback::Callback m_readFile;
|
ReadCallback::Callback m_readFile;
|
||||||
OptimiserSettings m_optimiserSettings;
|
OptimiserSettings m_optimiserSettings;
|
||||||
|
RevertStrings m_revertStrings = RevertStrings::Default;
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
std::map<std::string, std::set<std::string>> m_requestedContractNames;
|
std::map<std::string, std::set<std::string>> m_requestedContractNames;
|
||||||
bool m_generateIR;
|
bool m_generateIR;
|
||||||
|
63
libsolidity/interface/DebugSettings.h
Normal file
63
libsolidity/interface/DebugSettings.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Settings to aid debugging.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace dev
|
||||||
|
{
|
||||||
|
namespace solidity
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class RevertStrings
|
||||||
|
{
|
||||||
|
|
||||||
|
Default, // no compiler-generated strings, keep user-supplied strings
|
||||||
|
Strip, // no compiler-generated strings, remove user-supplied strings (if possible)
|
||||||
|
Debug, // add strings for internal reverts, keep user-supplied strings
|
||||||
|
VerboseDebug // add strings for internal reverts, add user-supplied strings if not provided
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string revertStringsToString(RevertStrings _str)
|
||||||
|
{
|
||||||
|
switch (_str)
|
||||||
|
{
|
||||||
|
case RevertStrings::Default: return "default";
|
||||||
|
case RevertStrings::Strip: return "strip";
|
||||||
|
case RevertStrings::Debug: return "debug";
|
||||||
|
case RevertStrings::VerboseDebug: return "verboseDebug";
|
||||||
|
}
|
||||||
|
// Cannot reach this.
|
||||||
|
return "INVALID";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::optional<RevertStrings> revertStringsFromString(std::string const& _str)
|
||||||
|
{
|
||||||
|
for (auto i: {RevertStrings::Default, RevertStrings::Strip, RevertStrings::Debug, RevertStrings::VerboseDebug})
|
||||||
|
if (revertStringsToString(i) == _str)
|
||||||
|
return i;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -350,7 +350,7 @@ std::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input)
|
|||||||
|
|
||||||
std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
|
std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
|
||||||
{
|
{
|
||||||
static set<string> keys{"parserErrorRecovery", "evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings"};
|
static set<string> keys{"parserErrorRecovery", "debug", "evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings"};
|
||||||
return checkKeys(_input, keys, "settings");
|
return checkKeys(_input, keys, "settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,6 +649,27 @@ boost::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompile
|
|||||||
ret.evmVersion = *version;
|
ret.evmVersion = *version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.isMember("debug"))
|
||||||
|
{
|
||||||
|
if (auto result = checkKeys(settings["debug"], {"revertStrings"}, "settings.debug"))
|
||||||
|
return *result;
|
||||||
|
|
||||||
|
if (settings["debug"].isMember("revertStrings"))
|
||||||
|
{
|
||||||
|
if (!settings["debug"]["revertStrings"].isString())
|
||||||
|
return formatFatalError("JSONError", "settings.debug.revertStrings must be a string.");
|
||||||
|
std::optional<RevertStrings> revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].asString());
|
||||||
|
if (!revertStrings)
|
||||||
|
return formatFatalError("JSONError", "Invalid value for settings.debug.revertStrings.");
|
||||||
|
if (*revertStrings != RevertStrings::Default && *revertStrings != RevertStrings::Strip)
|
||||||
|
return formatFatalError(
|
||||||
|
"UnimplementedFeatureError",
|
||||||
|
"Only \"default\" and \"strip\" are implemented for settings.debug.revertStrings for now."
|
||||||
|
);
|
||||||
|
ret.revertStrings = *revertStrings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
||||||
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
|
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
|
||||||
|
|
||||||
@ -751,6 +772,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
compilerStack.setParserErrorRecovery(_inputsAndSettings.parserErrorRecovery);
|
compilerStack.setParserErrorRecovery(_inputsAndSettings.parserErrorRecovery);
|
||||||
compilerStack.setRemappings(_inputsAndSettings.remappings);
|
compilerStack.setRemappings(_inputsAndSettings.remappings);
|
||||||
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
|
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
|
||||||
|
compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings);
|
||||||
compilerStack.setLibraries(_inputsAndSettings.libraries);
|
compilerStack.setLibraries(_inputsAndSettings.libraries);
|
||||||
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
||||||
compilerStack.setMetadataHash(_inputsAndSettings.metadataHash);
|
compilerStack.setMetadataHash(_inputsAndSettings.metadataHash);
|
||||||
@ -990,6 +1012,8 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
|||||||
return formatFatalError("JSONError", "Field \"settings.remappings\" cannot be used for Yul.");
|
return formatFatalError("JSONError", "Field \"settings.remappings\" cannot be used for Yul.");
|
||||||
if (!_inputsAndSettings.libraries.empty())
|
if (!_inputsAndSettings.libraries.empty())
|
||||||
return formatFatalError("JSONError", "Field \"settings.libraries\" cannot be used for Yul.");
|
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.");
|
||||||
|
|
||||||
Json::Value output = Json::objectValue;
|
Json::Value output = Json::objectValue;
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ private:
|
|||||||
std::map<h256, std::string> smtLib2Responses;
|
std::map<h256, std::string> smtLib2Responses;
|
||||||
langutil::EVMVersion evmVersion;
|
langutil::EVMVersion evmVersion;
|
||||||
std::vector<CompilerStack::Remapping> remappings;
|
std::vector<CompilerStack::Remapping> remappings;
|
||||||
|
RevertStrings revertStrings = RevertStrings::Default;
|
||||||
OptimiserSettings optimiserSettings = OptimiserSettings::minimal();
|
OptimiserSettings optimiserSettings = OptimiserSettings::minimal();
|
||||||
std::map<std::string, h160> libraries;
|
std::map<std::string, h160> libraries;
|
||||||
bool metadataLiteralSources = false;
|
bool metadataLiteralSources = false;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <libsolidity/interface/CompilerStack.h>
|
#include <libsolidity/interface/CompilerStack.h>
|
||||||
#include <libsolidity/interface/StandardCompiler.h>
|
#include <libsolidity/interface/StandardCompiler.h>
|
||||||
#include <libsolidity/interface/GasEstimator.h>
|
#include <libsolidity/interface/GasEstimator.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
|
|
||||||
#include <libyul/AssemblyStack.h>
|
#include <libyul/AssemblyStack.h>
|
||||||
|
|
||||||
@ -140,6 +141,17 @@ static string const g_strOptimizeRuns = "optimize-runs";
|
|||||||
static string const g_strOptimizeYul = "optimize-yul";
|
static string const g_strOptimizeYul = "optimize-yul";
|
||||||
static string const g_strOutputDir = "output-dir";
|
static string const g_strOutputDir = "output-dir";
|
||||||
static string const g_strOverwrite = "overwrite";
|
static string const g_strOverwrite = "overwrite";
|
||||||
|
static string const g_strRevertStrings = "revert-strings";
|
||||||
|
|
||||||
|
/// Possible arguments to for --revert-strings
|
||||||
|
static set<string> const g_revertStringsArgs
|
||||||
|
{
|
||||||
|
revertStringsToString(RevertStrings::Default),
|
||||||
|
revertStringsToString(RevertStrings::Strip),
|
||||||
|
revertStringsToString(RevertStrings::Debug),
|
||||||
|
revertStringsToString(RevertStrings::VerboseDebug)
|
||||||
|
};
|
||||||
|
|
||||||
static string const g_strSignatureHashes = "hashes";
|
static string const g_strSignatureHashes = "hashes";
|
||||||
static string const g_strSources = "sources";
|
static string const g_strSources = "sources";
|
||||||
static string const g_strSourceList = "sourceList";
|
static string const g_strSourceList = "sourceList";
|
||||||
@ -677,6 +689,11 @@ Allowed options)",
|
|||||||
"<libraryName>:<address> [, or whitespace] ...\n"
|
"<libraryName>:<address> [, or whitespace] ...\n"
|
||||||
"Address is interpreted as a hex string optionally prefixed by 0x."
|
"Address is interpreted as a hex string optionally prefixed by 0x."
|
||||||
)
|
)
|
||||||
|
(
|
||||||
|
g_strRevertStrings.c_str(),
|
||||||
|
po::value<string>()->value_name(boost::join(g_revertStringsArgs, ",")),
|
||||||
|
"Strip revert (and require) reason strings or add additional debugging information."
|
||||||
|
)
|
||||||
(
|
(
|
||||||
(g_argOutputDir + ",o").c_str(),
|
(g_argOutputDir + ",o").c_str(),
|
||||||
po::value<string>()->value_name("path"),
|
po::value<string>()->value_name("path"),
|
||||||
@ -797,6 +814,23 @@ Allowed options)",
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_args.count(g_strRevertStrings))
|
||||||
|
{
|
||||||
|
string revertStringsString = m_args[g_strRevertStrings].as<string>();
|
||||||
|
std::optional<RevertStrings> revertStrings = revertStringsFromString(revertStringsString);
|
||||||
|
if (!revertStrings)
|
||||||
|
{
|
||||||
|
serr() << "Invalid option for --" << g_strRevertStrings << ": " << revertStringsString << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*revertStrings != RevertStrings::Default && *revertStrings != RevertStrings::Strip)
|
||||||
|
{
|
||||||
|
serr() << "Only \"default\" and \"strip\" are implemented for --" << g_strRevertStrings << " for now." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_revertStrings = *revertStrings;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_args.count(g_argCombinedJson))
|
if (m_args.count(g_argCombinedJson))
|
||||||
{
|
{
|
||||||
vector<string> requests;
|
vector<string> requests;
|
||||||
@ -985,6 +1019,7 @@ bool CommandLineInterface::processInput()
|
|||||||
m_compiler->setLibraries(m_libraries);
|
m_compiler->setLibraries(m_libraries);
|
||||||
m_compiler->setParserErrorRecovery(m_args.count(g_argErrorRecovery));
|
m_compiler->setParserErrorRecovery(m_args.count(g_argErrorRecovery));
|
||||||
m_compiler->setEVMVersion(m_evmVersion);
|
m_compiler->setEVMVersion(m_evmVersion);
|
||||||
|
m_compiler->setRevertStringBehaviour(m_revertStrings);
|
||||||
// TODO: Perhaps we should not compile unless requested
|
// TODO: Perhaps we should not compile unless requested
|
||||||
|
|
||||||
m_compiler->enableIRGeneration(m_args.count(g_argIR));
|
m_compiler->enableIRGeneration(m_args.count(g_argIR));
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <libsolidity/interface/CompilerStack.h>
|
#include <libsolidity/interface/CompilerStack.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
#include <libyul/AssemblyStack.h>
|
#include <libyul/AssemblyStack.h>
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
@ -111,6 +112,8 @@ private:
|
|||||||
std::unique_ptr<dev::solidity::CompilerStack> m_compiler;
|
std::unique_ptr<dev::solidity::CompilerStack> m_compiler;
|
||||||
/// EVM version to use
|
/// EVM version to use
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
|
/// How to handle revert strings
|
||||||
|
RevertStrings m_revertStrings = RevertStrings::Default;
|
||||||
/// Chosen hash method for the bytecode metadata.
|
/// Chosen hash method for the bytecode metadata.
|
||||||
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
|
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
|
||||||
/// Whether or not to colorize diagnostics output.
|
/// Whether or not to colorize diagnostics output.
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <test/Options.h>
|
#include <test/Options.h>
|
||||||
|
|
||||||
#include <libsolidity/interface/OptimiserSettings.h>
|
#include <libsolidity/interface/OptimiserSettings.h>
|
||||||
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
|
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
@ -269,6 +270,7 @@ protected:
|
|||||||
bytes const& logData(size_t _logIdx) const;
|
bytes const& logData(size_t _logIdx) const;
|
||||||
|
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
|
solidity::RevertStrings m_revertStrings = solidity::RevertStrings::Default;
|
||||||
solidity::OptimiserSettings m_optimiserSettings = solidity::OptimiserSettings::minimal();
|
solidity::OptimiserSettings m_optimiserSettings = solidity::OptimiserSettings::minimal();
|
||||||
bool m_showMessages = false;
|
bool m_showMessages = false;
|
||||||
std::shared_ptr<EVMHost> m_evmHost;
|
std::shared_ptr<EVMHost> m_evmHost;
|
||||||
|
@ -87,6 +87,7 @@ eth::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
|
|||||||
{
|
{
|
||||||
Compiler compiler(
|
Compiler compiler(
|
||||||
dev::test::Options::get().evmVersion(),
|
dev::test::Options::get().evmVersion(),
|
||||||
|
RevertStrings::Default,
|
||||||
dev::test::Options::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()
|
dev::test::Options::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()
|
||||||
);
|
);
|
||||||
compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes());
|
compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes());
|
||||||
|
@ -284,6 +284,26 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
|
|||||||
check(sourceCode, false);
|
check(sourceCode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(metadata_revert_strings)
|
||||||
|
{
|
||||||
|
CompilerStack compilerStack;
|
||||||
|
char const* sourceCodeA = R"(
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
contract A {
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compilerStack.setSources({{"A", std::string(sourceCodeA)}});
|
||||||
|
compilerStack.setRevertStringBehaviour(RevertStrings::Strip);
|
||||||
|
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
|
||||||
|
|
||||||
|
std::string const& serialisedMetadata = compilerStack.metadata("A");
|
||||||
|
BOOST_CHECK(dev::test::isValidMetadata(serialisedMetadata));
|
||||||
|
Json::Value metadata;
|
||||||
|
BOOST_REQUIRE(jsonParseStrict(serialisedMetadata, metadata));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(metadata["settings"]["debug"]["revertStrings"], "strip");
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14800,6 +14800,55 @@ BOOST_AUTO_TEST_CASE(try_catch_library_call)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(strip_reason_strings)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract C {
|
||||||
|
function f(bool _x) public pure returns (uint) {
|
||||||
|
require(_x, "some reason");
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
function g(bool _x) public pure returns (uint) {
|
||||||
|
string memory x = "some indirect reason";
|
||||||
|
require(_x, x);
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
function f1(bool _x) public pure returns (uint) {
|
||||||
|
if (!_x) revert( /* */ "some reason" /* */ );
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
function g1(bool _x) public pure returns (uint) {
|
||||||
|
string memory x = "some indirect reason";
|
||||||
|
if (!_x) revert(x);
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
m_revertStrings = RevertStrings::Default;
|
||||||
|
compileAndRun(sourceCode, 0, "C");
|
||||||
|
|
||||||
|
if (
|
||||||
|
m_optimiserSettings == OptimiserSettings::minimal() ||
|
||||||
|
m_optimiserSettings == OptimiserSettings::none()
|
||||||
|
)
|
||||||
|
// check that the reason string IS part of the binary.
|
||||||
|
BOOST_CHECK(toHex(m_output).find("736f6d6520726561736f6e") != std::string::npos);
|
||||||
|
|
||||||
|
m_revertStrings = RevertStrings::Strip;
|
||||||
|
compileAndRun(sourceCode, 0, "C");
|
||||||
|
// check that the reason string is NOT part of the binary.
|
||||||
|
BOOST_CHECK(toHex(m_output).find("736f6d6520726561736f6e") == std::string::npos);
|
||||||
|
|
||||||
|
ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(7));
|
||||||
|
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs());
|
||||||
|
ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(8));
|
||||||
|
ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs());
|
||||||
|
ABI_CHECK(callContractFunction("f1(bool)", true), encodeArgs(9));
|
||||||
|
ABI_CHECK(callContractFunction("f1(bool)", false), encodeArgs());
|
||||||
|
ABI_CHECK(callContractFunction("g1(bool)", true), encodeArgs(10));
|
||||||
|
ABI_CHECK(callContractFunction("g1(bool)", false), encodeArgs());
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ bytes SolidityExecutionFramework::compileContract(
|
|||||||
m_compiler.reset();
|
m_compiler.reset();
|
||||||
m_compiler.setSources({{"", sourceCode}});
|
m_compiler.setSources({{"", sourceCode}});
|
||||||
m_compiler.setLibraries(_libraryAddresses);
|
m_compiler.setLibraries(_libraryAddresses);
|
||||||
|
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||||
m_compiler.setEVMVersion(m_evmVersion);
|
m_compiler.setEVMVersion(m_evmVersion);
|
||||||
m_compiler.setOptimiserSettings(m_optimiserSettings);
|
m_compiler.setOptimiserSettings(m_optimiserSettings);
|
||||||
m_compiler.enableIRGeneration(m_compileViaYul);
|
m_compiler.enableIRGeneration(m_compileViaYul);
|
||||||
|
@ -152,7 +152,11 @@ bytes compileFirstExpression(
|
|||||||
parametersSize--
|
parametersSize--
|
||||||
);
|
);
|
||||||
|
|
||||||
ExpressionCompiler(context, dev::test::Options::get().optimize).compile(*extractor.expression());
|
ExpressionCompiler(
|
||||||
|
context,
|
||||||
|
RevertStrings::Default,
|
||||||
|
dev::test::Options::get().optimize
|
||||||
|
).compile(*extractor.expression());
|
||||||
|
|
||||||
for (vector<string> const& function: _functions)
|
for (vector<string> const& function: _functions)
|
||||||
context << context.functionEntryLabel(dynamic_cast<FunctionDefinition const&>(
|
context << context.functionEntryLabel(dynamic_cast<FunctionDefinition const&>(
|
||||||
|
Loading…
Reference in New Issue
Block a user