mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9298 from ethereum/yul-evm-version-tests
Use different error code for various EVM features in Yul
This commit is contained in:
commit
889131321a
@ -264,7 +264,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
if (f->literalArguments)
|
if (f->literalArguments)
|
||||||
needsLiteralArguments = &f->literalArguments.value();
|
needsLiteralArguments = &f->literalArguments.value();
|
||||||
|
|
||||||
warnOnInstructions(_funCall);
|
validateInstructions(_funCall);
|
||||||
}
|
}
|
||||||
else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
|
else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
|
||||||
[&](Scope::Variable const&)
|
[&](Scope::Variable const&)
|
||||||
@ -282,7 +282,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
if (!warnOnInstructions(_funCall))
|
if (!validateInstructions(_funCall))
|
||||||
m_errorReporter.declarationError(4619_error, _funCall.functionName.location, "Function not found.");
|
m_errorReporter.declarationError(4619_error, _funCall.functionName.location, "Function not found.");
|
||||||
yulAssert(!watcher.ok(), "Expected a reported error.");
|
yulAssert(!watcher.ok(), "Expected a reported error.");
|
||||||
}
|
}
|
||||||
@ -541,16 +541,16 @@ void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, Sour
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsmAnalyzer::warnOnInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location)
|
bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location)
|
||||||
{
|
{
|
||||||
auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulString(_instructionIdentifier));
|
auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulString(_instructionIdentifier));
|
||||||
if (builtin && builtin->instruction.has_value())
|
if (builtin && builtin->instruction.has_value())
|
||||||
return warnOnInstructions(builtin->instruction.value(), _location);
|
return validateInstructions(builtin->instruction.value(), _location);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation const& _location)
|
bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location)
|
||||||
{
|
{
|
||||||
// We assume that returndatacopy, returndatasize and staticcall are either all available
|
// We assume that returndatacopy, returndatasize and staticcall are either all available
|
||||||
// or all not available.
|
// or all not available.
|
||||||
@ -558,9 +558,9 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation
|
|||||||
// Similarly we assume bitwise shifting and create2 go together.
|
// Similarly we assume bitwise shifting and create2 go together.
|
||||||
yulAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
|
yulAssert(m_evmVersion.hasBitwiseShifting() == m_evmVersion.hasCreate2(), "");
|
||||||
|
|
||||||
auto errorForVM = [&](string const& vmKindMessage) {
|
auto errorForVM = [&](ErrorId _errorId, string const& vmKindMessage) {
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
7079_error,
|
_errorId,
|
||||||
_location,
|
_location,
|
||||||
"The \"" +
|
"The \"" +
|
||||||
boost::to_lower_copy(instructionInfo(_instr).name)
|
boost::to_lower_copy(instructionInfo(_instr).name)
|
||||||
@ -577,21 +577,21 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation
|
|||||||
_instr == evmasm::Instruction::RETURNDATACOPY ||
|
_instr == evmasm::Instruction::RETURNDATACOPY ||
|
||||||
_instr == evmasm::Instruction::RETURNDATASIZE
|
_instr == evmasm::Instruction::RETURNDATASIZE
|
||||||
) && !m_evmVersion.supportsReturndata())
|
) && !m_evmVersion.supportsReturndata())
|
||||||
errorForVM("only available for Byzantium-compatible");
|
errorForVM(7756_error, "only available for Byzantium-compatible");
|
||||||
else if (_instr == evmasm::Instruction::STATICCALL && !m_evmVersion.hasStaticCall())
|
else if (_instr == evmasm::Instruction::STATICCALL && !m_evmVersion.hasStaticCall())
|
||||||
errorForVM("only available for Byzantium-compatible");
|
errorForVM(1503_error, "only available for Byzantium-compatible");
|
||||||
else if ((
|
else if ((
|
||||||
_instr == evmasm::Instruction::SHL ||
|
_instr == evmasm::Instruction::SHL ||
|
||||||
_instr == evmasm::Instruction::SHR ||
|
_instr == evmasm::Instruction::SHR ||
|
||||||
_instr == evmasm::Instruction::SAR
|
_instr == evmasm::Instruction::SAR
|
||||||
) && !m_evmVersion.hasBitwiseShifting())
|
) && !m_evmVersion.hasBitwiseShifting())
|
||||||
errorForVM("only available for Constantinople-compatible");
|
errorForVM(6612_error, "only available for Constantinople-compatible");
|
||||||
else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2())
|
else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2())
|
||||||
errorForVM("only available for Constantinople-compatible");
|
errorForVM(6166_error, "only available for Constantinople-compatible");
|
||||||
else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
|
else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
|
||||||
errorForVM("only available for Constantinople-compatible");
|
errorForVM(7110_error, "only available for Constantinople-compatible");
|
||||||
else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID())
|
else if (_instr == evmasm::Instruction::CHAINID && !m_evmVersion.hasChainID())
|
||||||
errorForVM("only available for Istanbul-compatible");
|
errorForVM(1561_error, "only available for Istanbul-compatible");
|
||||||
else if (_instr == evmasm::Instruction::PC)
|
else if (_instr == evmasm::Instruction::PC)
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
2450_error,
|
2450_error,
|
||||||
@ -601,7 +601,7 @@ bool AsmAnalyzer::warnOnInstructions(evmasm::Instruction _instr, SourceLocation
|
|||||||
"\" instruction is deprecated and will be removed in the next breaking release."
|
"\" instruction is deprecated and will be removed in the next breaking release."
|
||||||
);
|
);
|
||||||
else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance())
|
else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance())
|
||||||
errorForVM("only available for Istanbul-compatible");
|
errorForVM(3672_error, "only available for Istanbul-compatible");
|
||||||
else if (
|
else if (
|
||||||
_instr == evmasm::Instruction::JUMP ||
|
_instr == evmasm::Instruction::JUMP ||
|
||||||
_instr == evmasm::Instruction::JUMPI ||
|
_instr == evmasm::Instruction::JUMPI ||
|
||||||
|
@ -110,12 +110,12 @@ private:
|
|||||||
Scope& scope(Block const* _block);
|
Scope& scope(Block const* _block);
|
||||||
void expectValidType(YulString _type, langutil::SourceLocation const& _location);
|
void expectValidType(YulString _type, langutil::SourceLocation const& _location);
|
||||||
void expectType(YulString _expectedType, YulString _givenType, langutil::SourceLocation const& _location);
|
void expectType(YulString _expectedType, YulString _givenType, langutil::SourceLocation const& _location);
|
||||||
bool warnOnInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location);
|
|
||||||
bool warnOnInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
|
|
||||||
|
|
||||||
bool warnOnInstructions(FunctionCall const& _functionCall)
|
bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location);
|
||||||
|
bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
|
||||||
|
bool validateInstructions(FunctionCall const& _functionCall)
|
||||||
{
|
{
|
||||||
return warnOnInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
|
return validateInstructions(_functionCall.functionName.name.str(), _functionCall.functionName.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
yul::ExternalIdentifierAccess::Resolver m_resolver;
|
yul::ExternalIdentifierAccess::Resolver m_resolver;
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
contract C {
|
||||||
|
function f() pure external {
|
||||||
|
assembly {
|
||||||
|
let s := returndatasize()
|
||||||
|
returndatacopy(0, 0, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g() view external returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
ret := staticcall(0, gas(), 0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=byzantium
|
||||||
|
// ----
|
@ -0,0 +1,21 @@
|
|||||||
|
contract C {
|
||||||
|
function f() pure external {
|
||||||
|
assembly {
|
||||||
|
let s := returndatasize()
|
||||||
|
returndatacopy(0, 0, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g() view external returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
ret := staticcall(0, gas(), 0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: =homestead
|
||||||
|
// ----
|
||||||
|
// TypeError 7756: (86-100): The "returndatasize" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead").
|
||||||
|
// DeclarationError 3812: (77-102): Variable count mismatch: 1 variables and 0 values.
|
||||||
|
// TypeError 7756: (115-129): The "returndatacopy" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead").
|
||||||
|
// TypeError 1503: (245-255): The "staticcall" instruction is only available for Byzantium-compatible VMs (you are currently compiling for "homestead").
|
||||||
|
// DeclarationError 8678: (238-277): Variable count does not match number of values (1 vs. 0)
|
@ -0,0 +1,17 @@
|
|||||||
|
contract C {
|
||||||
|
function f() view external returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
ret := shl(gas(), 5)
|
||||||
|
ret := shr(ret, 2)
|
||||||
|
ret := sar(ret, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g() external returns (address ret) {
|
||||||
|
assembly {
|
||||||
|
ret := create2(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=constantinople
|
||||||
|
// ----
|
@ -0,0 +1,25 @@
|
|||||||
|
contract C {
|
||||||
|
function f() view external returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
ret := shl(gas(), 5)
|
||||||
|
ret := shr(ret, 2)
|
||||||
|
ret := sar(ret, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g() external returns (address ret) {
|
||||||
|
assembly {
|
||||||
|
ret := create2(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: =byzantium
|
||||||
|
// ----
|
||||||
|
// TypeError 6612: (103-106): The "shl" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium").
|
||||||
|
// DeclarationError 8678: (96-116): Variable count does not match number of values (1 vs. 0)
|
||||||
|
// TypeError 6612: (136-139): The "shr" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium").
|
||||||
|
// DeclarationError 8678: (129-147): Variable count does not match number of values (1 vs. 0)
|
||||||
|
// TypeError 6612: (167-170): The "sar" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium").
|
||||||
|
// DeclarationError 8678: (160-178): Variable count does not match number of values (1 vs. 0)
|
||||||
|
// TypeError 6166: (283-290): The "create2" instruction is only available for Constantinople-compatible VMs (you are currently compiling for "byzantium").
|
||||||
|
// DeclarationError 8678: (276-302): Variable count does not match number of values (1 vs. 0)
|
@ -13,7 +13,7 @@ contract C {
|
|||||||
// ====
|
// ====
|
||||||
// EVMVersion: =petersburg
|
// EVMVersion: =petersburg
|
||||||
// ----
|
// ----
|
||||||
// TypeError 7079: (101-108): The "chainid" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg").
|
// TypeError 1561: (101-108): The "chainid" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg").
|
||||||
// DeclarationError 8678: (95-110): Variable count does not match number of values (1 vs. 0)
|
// DeclarationError 8678: (95-110): Variable count does not match number of values (1 vs. 0)
|
||||||
// TypeError 7079: (215-226): The "selfbalance" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg").
|
// TypeError 3672: (215-226): The "selfbalance" instruction is only available for Istanbul-compatible VMs (you are currently compiling for "petersburg").
|
||||||
// DeclarationError 8678: (209-228): Variable count does not match number of values (1 vs. 0)
|
// DeclarationError 8678: (209-228): Variable count does not match number of values (1 vs. 0)
|
Loading…
Reference in New Issue
Block a user